如何调试和打印模板别名类型 C++

How to debug and print a template alias type c++

我有一些正在尝试调试的嵌套类型定义。我要做的第一件事是将它们打印出来,这样我就可以看到它们是如何实例化的。

例如

 using tt = std::conditional<conditionForType1, type_1, type_2>;

其中 type_1type_2 是另外两个评估的别名。如何打印tttype_1type_2

的内容

我使用编译器为我处理这个问题。通过声明一个 class 模板,例如

template <typename T>
struct type;

并且不定义它,您可以在代码中使用它,例如

int main()
{
    struct foo {};
    struct bar {};
    
    foo f;
    
    type<int>{};
    type<decltype(f)>{};
    type<bar>{};
}

这会给你一个编译器错误,比如

main.cpp: In function 'int main()':
main.cpp:25:15: error: invalid use of incomplete type 'struct type<int>'
   25 |     type<int>{};
      |               ^
main.cpp:14:8: note: declaration of 'struct type<int>'
   14 | struct type;
      |        ^~~~
main.cpp:26:23: error: invalid use of incomplete type 'struct type<main()::foo>'
   26 |     type<decltype(f)>{};
      |                       ^
main.cpp:14:8: note: declaration of 'struct type<main()::foo>'
   14 | struct type;
      |        ^~~~
main.cpp:27:15: error: invalid use of incomplete type 'struct type<main()::bar>'
   27 |     type<bar>{};
      |               ^
main.cpp:14:8: note: declaration of 'struct type<main()::bar>'
   14 | struct type;
      |        ^~~~

它会为您提供模板参数中使用的类型作为方便的错误消息。

typeid operator returns an object of type type_info,其中有一个name()方法。您可以使用它来获取类型的字符串表示形式。

std::cout << typeid(tt).name() << '\n';

如果您使用 , there is an API,您可以调用将名称分解为更易于阅读的名称。在我的系统上,程序:

using tt = std::conditional<true, int, double>;

int main () {
    int status;
    auto &&ti = typeid(tt);
    char *pretty = abi::__cxa_demangle(ti.name(), 0, 0, &status);
    std::cout << ti.name() << '\n';
    std::cout << pretty << '\n';
    free(pretty);
}

产生输出:

St11conditionalILb1EidE
std::conditional<true, int, double>

Try it online!

一种快速而肮脏的方法:

template <typename T>
void print_type()
{
    #ifndef _MSC_VER
    std::cout << __PRETTY_FUNCTION__ << '\n';
    #else
    std::cout << __FUNCSIG__ << '\n';
    #endif
}

具体打印什么取决于编译器。对于 print_type<int>();,我的 Clang 打印 void print_type() [T = int].

请参阅 this thread 从此类字符串中删除类型名称以外的任何内容。