如何调试和打印模板别名类型 C++
How to debug and print a template alias type c++
我有一些正在尝试调试的嵌套类型定义。我要做的第一件事是将它们打印出来,这样我就可以看到它们是如何实例化的。
例如
using tt = std::conditional<conditionForType1, type_1, type_2>;
其中 type_1
和 type_2
是另外两个评估的别名。如何打印tt
、type_1
和type_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';
如果您使用 g++, 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>
一种快速而肮脏的方法:
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 从此类字符串中删除类型名称以外的任何内容。
我有一些正在尝试调试的嵌套类型定义。我要做的第一件事是将它们打印出来,这样我就可以看到它们是如何实例化的。
例如
using tt = std::conditional<conditionForType1, type_1, type_2>;
其中 type_1
和 type_2
是另外两个评估的别名。如何打印tt
、type_1
和type_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';
如果您使用 g++, 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>
一种快速而肮脏的方法:
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 从此类字符串中删除类型名称以外的任何内容。