【问题标题】:Is there any way to convert decltype to string in a macro?有没有办法在宏中将 decltype 转换为字符串?
【发布时间】:2013-07-08 10:27:07
【问题描述】:

有什么方法可以在 C++ 宏中评估 decltype 吗?我的主要动机是创建一个能够确定this 类型并将其转换为字符串的宏。

如果无法使用decltype,在类声明中使用的宏还有其他方法可以将类的类型作为字符串获取吗?

【问题讨论】:

    标签: c++ c-preprocessor decltype


    【解决方案1】:

    有什么方法可以在 C++ 宏中评估 decltype

    不,因为宏在之前 decltype 被严格评估。

    据我所知,没有办法将类的名称作为宏,句号。任何这样的方式都必须得到编译器生成的宏的支持。

    但是,您可以使用 typeid 来获取重整名称(严格来说,实现定义的表示),然后使用特定于编译器的工具从中检索重整名称。

    例如,GCC 提供了demangling library 来执行此操作。

    这是一个最小的例子@987654322@

    #define THIS_CLASS_NAME() demangled(typeid(*this).name())
    
    std::string demangled(char const* tname) {
        std::unique_ptr<char, void(*)(void*)>
            name{abi::__cxa_demangle(tname, 0, 0, nullptr), std::free};
        return {name.get()};
    }
    

    用法:

    namespace foo {
        template <typename T>
        struct bar {
            bar() { std::cout << THIS_CLASS_NAME() << '\n'; }
        };
    }
    
    int main() {
        foo::bar<int> b;
    }
    

    产量:

    foo::bar<int>
    

    【讨论】:

      【解决方案2】:

      宏在编译任何代码之前会被扩展,因此很遗憾它们没有任何类型的概念。

      根据您的需要,您也许可以改用特征类。从理论上讲,它比 RTTI 和 typeid 更高效、更便携,但它只适用于你明确告诉它的类型。例如:

      template <typename T>
      struct Traits
      {
          static const char * TYPE_NAME;
      };
      // Generic definition as a fall-back:
      template <typename T> const char * Traits<T>::TYPE_NAME = "unknown";
      
      // Explicit definitions
      template < > const char * Traits< int >::TYPE_NAME = "int";
      template < > const char * Traits< float >::TYPE_NAME = "float";
      template < > const char * Traits< ExampleClass >::TYPE_NAME = "ExampleClass";
      

      显式定义有点麻烦,所以你可以创建一个宏来让它们更具可读性:

      #define DECLARE_TYPE_TRAIT(name) template < > const char * Traits<name>::TYPE_NAME = #name;
      
      DECLARE_TYPE_TRAITS(int)
      DECLARE_TYPE_TRAITS(float)
      DECLARE_TYPE_TRAITS(ExampleClass)
      

      在您的代码中使用特征类非常简单。您只需在要查找的任何类型上实例化特征模板,然后访问 TYPE_NAME 成员:

      int foo;
      ExampleClass blah;
      
      cout << Traits<decltype(foo)>::TYPE_NAME << endl;
      cout << Traits<decltype(blah)>::TYPE_NAME << endl;
      

      【讨论】:

      • 谢谢 - 我所寻求的解决方案实际上只是使用类型名作为宏的参数 - 它实际上与此相同,尽管更具体地针对我的特定情况。
      猜你喜欢
      • 2023-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-17
      • 1970-01-01
      • 1970-01-01
      • 2021-04-04
      • 2021-03-03
      相关资源
      最近更新 更多