《Effective Modern C++》Item 4: Know how to view deduced types.

引子

本条目就相当轻松了,主要是S.M.老爷子教大家如何查看类型,毕竟之前3节讲了这么多,对于C++1x的新手来说上手还是要花一段时间的,所以从下面3个角度介绍如何查看类型:

  • IDE
  • 编译器时诊断
  • 运行时输出

正文

正文中,我们需要获得下面两个变量的类型:

const int theAnswer = 42; 

auto x = theAnswer;
auto y = &theAnswer;

1.IDE

IDE是最简单的获取方式,现在大部分的IDE都可以帮助用户获取变量类型。这在大部分时候是有效的,但是当类型比较复杂时,可能你的IDE就无法给出正确的结果了。

2.编译器诊断

利用编译时的错误信息,也可以帮助我们诊断类型。我们先声明这样一个类:

template<typename T>       // declaration only for TD;
class TD;                  // TD == "Type Displayer"

注意到这个类并没有被定义,当然也就没有构造器了,那么我们在初始化一个该类的对象例如:

TD<decltype(x)> xType;     // elicit errors containing
TD<decltype(y)> yType;     // x's and y's types

编译上面的代码时,编译器一定会报错,例如:

error: aggregate 'TD<int> xType' has incomplete type and cannot be defined
error: aggregate 'TD<const int *> yType' has incomplete type and cannot be defined

这样我们就获得了x,y的类型。

3.运行时获取

运行时获取的好处在于我们可以控制输出格式,但是如何获得你想要的输出格式是一个挑战。我们先从最简单的方法开始:

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

不同的编译器运行时输出不同的结果,例如gnu和clang会输出x是”i“以及y是”PKi“;而微软的编译器则会分别输出”int“和”int const *“。目前为止,一切都好,可能你以为已经OK了。但是实际上考虑到如下代码:

template<typename T>                // template function to be called
void f(const T& param);

std::vector<Widget> createVec();    // factory function

const auto vw = createVec();        // init vw w/factory return

if (!vw.empty()) {
  f(&vw[0]);                        // call f
  ... 
}

如果你调用typeid来输出函数fTparam的类型,不论哪个编译器,你都会得到错误的结果。例如微软的编译器会告诉你:二者的类型都是class Widget const *。但我们观察f的定义可以看出,显然param的类型应该比T多一个const &。这是由于我们这里typeid是传值的,在用模板规则推导类型时,由Item 1可知会丢失const T&中的const和引用属性。

所以最后我们需要祭出大杀器boost库,即里面的Boost.TypeIndex。代码如下

#include <boost/type_index.hpp>
template<typename T>
void f(const T& param)
{
  using std::cout;
  using boost::typeindex::type_id_with_cvr;

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

  // show param's type
  cout << "param = "
       << type_id_with_cvr<decltype(param)>().pretty_name()
       << '\n';
}

最后我们运行会输出我们想要的结果:

T =     class Widget const *
param = class Widget const * const &

总结

最后简单的两条tips:

1.类型推导可以通过IDE,编译器错误信息,以及Boost.TypeIndex
2.某些工具的结果不一定准确或者难以阅读,所以理解C++类型推导规则仍然很重要

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值