《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++类型推导规则仍然很重要

Coming to grips with C++11 and C++14 is more than a matter of familiarizing yourself with the features they introduce (e.g., auto type declarations, move semantics, lambda expressions, and concurrency support). The challenge is learning to use those features effectively—so that your software is correct, efficient, maintainable, and portable. That’s where this practical book comes in. It describes how to write truly great software using C++11 and C++14—i.e. using modern C++. Topics include: The pros and cons of braced initialization, noexcept specifications, perfect forwarding, and smart pointer make functions The relationships among std::move, std::forward, rvalue references, and universal references Techniques for writing clear, correct, effective lambda expressions How std::atomic differs from volatile, how each should be used, and how they relate to C++'s concurrency API How best practices in "old" C++ programming (i.e., C++98) require revision for software development in modern C++ Effective Modern C++ follows the proven guideline-based, example-driven format of Scott Meyers' earlier books, but covers entirely new material. "After I learned the C++ basics, I then learned how to use C++ in production code from Meyer's series of Effective C++ books. Effective Modern C++ is the most important how-to book for advice on key guidelines, styles, and idioms to use modern C++ effectively and well. Don't own it yet? Buy this one. Now". -- Herb Sutter, Chair of ISO C++ Standards Committee and C++ Software Architect at Microsoft
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值