有没有办法将decltype转换为宏中的字符串?

时间:2013-07-08 10:27:07

标签: c++ c-preprocessor decltype

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

如果无法使用decltype,那么在类声明中使用的宏是否可以将类的类型作为字符串获取?

2 个答案:

答案 0 :(得分:5)

  

有什么方法可以评估C ++宏中的decltype吗?

不,因为在 decltype之前严格评估了

据我所知,没有办法将类的名称作为宏,完全停止。任何这样的方式都必须由编译器生成的宏支持。

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

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

这是一个最小的例子 online demo

#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>

答案 1 :(得分:4)

在编译任何代码之前会扩展宏,所以不幸的是它们没有任何类型的概念。

根据您的需要,您可能会使用traits类。理论上它比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)

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

int foo;
ExampleClass blah;

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