其他分享
首页 > 其他分享> > c-打印给定类型名称的模板

c-打印给定类型名称的模板

作者:互联网

我想打印出一种类型的名称以用于调试,因此,我创建了一个可以完成上述功能的函数(实际上,我是从另一个SO答案中借用的,现在找不到),该函数如下所示:

template <typename T> std::string TypeName(T)
{
    auto name = typeid(T).name();
    int status = 0;

    std::unique_ptr<char, void(*)(void*)> res {
        abi::__cxa_demangle(name, NULL, NULL, &status),
        std::free
    };

    return ((status == 0) ? res.get() : name);
}

Live Demo

它工作正常:

int i = 0;
float f = 0.f;

std::cout << TypeName(i) << '\n'; // int
std::cout << TypeName(f) << '\n'; // float, so far so good

std::cout << TypeName(&i) << '\n'; // int *
std::cout << TypeName(&f) << '\n'; // float *, as expected

但是它缺乏处理top-level cv-cualifiers和参考的能力:

const int ci = 1;
const float cf = 1.f;

std::cout << TypeName(ci) << '\n'; // int! (instead of const int)
std::cout << TypeName(cf) << '\n'; // float! (instead of const float)

int &ri = i;
float &rf = f;

std::cout << TypeName(ri) << '\n'; // int! (instead of int &)
std::cout << TypeName(rf) << '\n'; // float! (instead of float &)

好吧,我不能说这是意外的,因为函数TypeName是函数模板,类型T遵循模板类型推导,但是这个问题使整个事情几乎毫无用处.

因此,我的问题是:是否可以做些什么来创建一个模板函数(可以将任何类型的输入作为输入)来获取类型名称,而又不会丢失顶级的cv-cualifiers和引用?

提前致谢.

解决方法:

唯一可以区分作为id表达式的左值与作为引用的左值之间的区别的C语言构造是decltype.这是一个如何使用它的示例,包括(不使用)宏来保持您已经拥有的相同调用模式:

template <typename T> std::string TypeName() {
    auto name = typeid(T()).name();  // function type, not a constructor call!
    int status = 0;

    std::unique_ptr<char, void(*)(void*)> res {
        abi::__cxa_demangle(name, NULL, NULL, &status),
        std::free
    };

    std::string ret((status == 0) ? res.get() : name);
    if (ret.substr(ret.size() - 3) == " ()") ret.resize(ret.size() - 3);
    return ret;
}
#define TypeName(e) TypeName<decltype(e)>()

因为abi :: __ cxa_demangle忽略顶级cv和引用限定符,所以我们构造了一个函数类型,然后去除了后括号.

这给出了int const,int&amp ;、 int const&按要求.

标签:name-mangling,c,templates
来源: https://codeday.me/bug/20191010/1888725.html