8

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

如果无法decltype使用在类声明中使用的宏是否可以通过其他方式将类的类型作为字符串获取?

4

2 回答 2

7

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

不,因为宏 decltype.

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

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

例如,GCC 提供了demanling 库来执行此操作。

这是一个最小的例子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>
于 2013-07-08T10:33:05.670 回答
6

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

不过,根据您的需要,您也许可以使用特征类。从理论上讲,它比 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;
于 2013-07-08T11:02:19.650 回答