【问题标题】:Pretty-print types and class template along with all its template arguments漂亮的打印类型和类模板及其所有模板参数
【发布时间】:2012-12-15 01:11:44
【问题描述】:

由于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&lt;int&gt; 作为模板参数传递给它时,它会返回"Y"。以下是每个用户类模板部分专用的方法。

#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&lt;template_type&lt;Ts...&gt;&gt; 只是 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)

请参阅the working code here 了解其他详细信息。到目前为止效果很好。

但现在我正在对此进行改进,并希望添加对非类型模板参数和混合模板参数的支持:

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>

我该怎么做?一般如何获取此类模板的名称及其参数?

【问题讨论】:

  • GCC 有一个 demangler 可以打印出非常有用的模板类名...
  • @KerrekSB:是的,但这不是标准的。我想要在任何地方都能使用的东西。

标签: c++ templates c++11 pretty-print variadic-templates


【解决方案1】:

很抱歉,这是一个“否定答案”(我赞成您的问题),但恐怕您不能这样做。即使只考虑接受非类型参数的同类列表(例如template&lt;int, int&gt;template&lt;char, char, char&gt; 等)的模板类,您也需要这种特化:

template<typename T>
struct single_type
{
    // ...
};

template<typename U, template<U...> class C, U... Us>
struct single_type<C<Us...>>
{
    // ...
};

这种特化是合法的,但没有用,因为参数类型U 永远无法推导出来。您可以为最常见类型(int...char... 等)的统一文字列表定义专用特化,但仍然无法涵盖异构类型的序列,更不用说混合参数的序列了。

恐怕我们必须等待 C++ 支持反射才能实现您的目标。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-16
    • 2014-01-29
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    • 1970-01-01
    • 1970-01-01
    • 2021-03-08
    相关资源
    最近更新 更多