采用何种工具来查看型别推导结果,取决于在软件开发过程的哪个阶段需要该信息。三个可能的阶段:撰写代码阶段、编译阶段和运行时阶段。

IDE编辑器

IDE 中的代码编辑器通常会在你将鼠标指针悬停至某个程序实体,如变量、形参、函数等时,显示出该实体的类型。例如:

1
2
3
4
const int theAnswer = 42;

auto x = theAnswer;
auto y = &theAnswer;

IDE 编辑器很可能会显示出,x 的类型推导结果是 int, 而 y 则是 const int*。

但是如果遇到较为复杂的类型,IDE显示的信息就不太有用了。

编译器诊断信息

一条有效途径是使用该类型导致某些编译错误。而报告错误的消息几乎肯定会提及导致该错误的类型。

例如:

1
2
template<typename T> //只声明TD而不定义
class TD; // TD是“类型显示类”的缩写

只要试图具现该模板,就会诱发一个错误信息,原因是找不到具现模板所需要的定义。

运行时输出

使用 printf来显示类型信息,这种方法只有到了运行期才能使用,却可以对类型输出的格式提供完全的控制。

1
2
std::cout << typeid(x).name() << '\n'; //display types for x and y
std::cout << typeid(y).name() << '\n';

但是推导结果并不可靠,根据C++标准,std::type_info::name处理类型的方式类似于按值传递参数,这意味着它会忽略掉引用和顶层的const/volatile修饰符。

推荐方案:使用 Boost.TypeIndex库
例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <boost/type_index.hpp>

template<typename T>
void f(const T& param)
{
using std::cout;
using boost::typeindex::type_id_with_cvr;

//显示T
cout << "T = "
<< type_id_with_cvr<T>().pretty_name()
<< '\n';

//显示param类型
cout << "param = "
<< type_id_with_cvr<decltype(param)>().pretty_name()
<< '\n';
}

它提供的type_id_with_cvr()函数会保留类型的const、volatile和引用修饰符。其成员函数pretty_name产生一个包含人类可读的类型表示的std::string。

总结

  • 利用 IDE 编辑器、编译器错误消息和 Boost.Typelndex 库常常能够查看到推导而得的类型。
  • 有些工具产生的结果可能会无用,或者不准确。所以,理解 C++类型推导规则是必要的。