2013-07-08 160 views
4

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

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

回答

4

有没有什么办法可以在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> 
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) 

使用在你的代码的特性类是很容易的。你只需实例化要查找任何类型的特征模板,并访问TYPE_NAME成员:

int foo; 
ExampleClass blah; 

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

谢谢 - 我去,实际上只是使用类型名作为参数传递给宏的解决方案 - 这是有效的与此相同,但更具体到我的具体情况。 –

相关问题