由于typeid(T).name()
不返回人类可以理解的类型名称,因此如果我们想将模板参数的名称打印到某个类模板,它对我们没有多大帮助,尤其是在我们调试时。我们经常想在调试时这样写:
print<Args...>(cout); //dump the names of all types to stdout!
所以我正在编写漂亮的打印实用程序,它给了我类模板的名称。好吧,通过一些示例用法更容易理解它:
print<int>(cout); //prints int
print<int, double, char>(cout); //prints int, double, char
print<std::string>(cout); //prints std::basic_string<char, .. etc>
print<std::wstring>(cout); //prints std::basic_string<wchar_t, .. etc>
print<X<int,Y<int>>>(cout); //prints X<int, Y<int>>
在内部,我正在使用一个名为的类模板,当我将它作为模板参数传递给它时,template_name
它会返回我。以下是每个用户类模板部分专用的方法。"Y"
Y<int>
#define DEFINE_TEMPLATE_NAME(template_type) \
template<typename ... Ts>\
struct template_name<template_type<Ts...>>\
{\
static const char* name()\
{\
return #template_type;\
}\
};
并且用户需要使用这个宏来注册他的模板类:
DEFINE_TEMPLATE_NAME(std::basic_string);
DEFINE_TEMPLATE_NAME(std::vector);
DEFINE_TEMPLATE_NAME(X); //X is a class template
DEFINE_TEMPLATE_NAME(Y); //Y is a class template
之所以有效,是因为特化是仅类型template_name<template_type<Ts...>>
的可变类模板,这意味着只要所有模板参数都是types,它就会返回类模板的名称。它还能够打印函数类型和成员函数类型:
typedef void fun(int,int);
//lets use snl::name() which returns name instead of printing!
std::cout << snl::name<fun>(); //prints : void(int,int)
std::cout << snl::name<fun*>(); //prints : void(*)(int,int)
请在此处查看工作代码以及其他详细信息。到目前为止效果很好。
但现在我正在对此进行改进,并希望添加对非类型模板参数和混合模板参数的支持:
template<int...>
struct Z{};
//non-type template arguments : 1,2,3
snd::print<Z<1,2,3>>(cout); //should print Z<1,2,3>
//mixed template arguments : int, 100
snd::print<std::array<int,100>>(cout); //should print std::array<int,100>
我该怎么做?一般如何获取此类模板的名称及其参数?