Effective Modern C++ Item 4

Know how to view deduced types

在 C++ 程序中, 有很多方法可以查看类型推导的结果:编辑代码的时候,在编译期间,在运行时。

IDE 编译器

在IDE中的代码编辑器通常可以显示程序代码中变量,函数,参数的类型。为此,代码必须处于可编译状态,因为IDE之所以能提供这些信息是因为一个C++编译器(或者至少是前端中的一个部分)运行于IDE中。

编译器诊断

另一个获得推导结果的方法是使用编译器出错时提供的错误消息。

举个例子,可以声明一个类模板但不定义

1
2
3
4
5
6
7
8
9
template<typename T>                //只对TD进行声明
class TD; //TD == "Type Displayer"

const int theAnswer = 42;
auto x = theAnswer;
auto y = &theAnswer;

TD<decltype(x)> xType; //引出包含x和y
TD<decltype(y)> yType; //的类型的错误消息

如果尝试实例化这个类模板就会引出一个错误消息:

1
2
error: 'xType' uses undefined class 'TD<int>'
error: 'yType' uses undefined class 'TD<const int *>'

运行时输出

在运行时显示类型的一个非常基本的用法是通过 typeidstd::type_info::name这两个内置函数:

1
2
std::cout << typeid(x).name() << '\n';  //显示x和y的类型
std::cout << typeid(y).name() << '\n';

然而std::type_info::name并不总是正确,std::type_info::name规范批准像传值形参一样来对待这些类型。

Boost TypeIndex库(通常写作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';
}

boost::typeindex::type_id_with_cvr获取一个类型实参(我们想获得相应信息的那个类型),它不消除实参的constvolatile和引用修饰符(因此模板名中有“with_cvr”)。

重点

  • 使用 IDE 编辑器、编译器错误消息和 Boost TypeIndex 库经常可以方便地看到推导类型。
  • 一些工具的结果可能既无帮助也不准确, 因此了解 C++ 的类型推导规则仍然是必不可少的。