有什么方法可以评估C ++宏中的decltype
吗?我的主要动机是创建一个能够确定this
类型并将其转换为字符串的宏。
如果无法使用decltype
,那么在类声明中使用的宏是否可以将类的类型作为字符串获取?
答案 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;