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

  IDE编译器

  IDE中的代码编译器通常会在你将鼠标指针选停止某个程序实体,如变量、形参、函数等时,显示出该实体的型别。例如以下这段代码:

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

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

  而让这种方法奏效,代码就多多少少要处于一种可编译状态。因为让IDE提供此类信息的工作原理是让C++编译器(或至少也是其前端)在IDE内执行一轮。如果该编译器不能在分析你的代码时得到足够的有用信息,自然也就无法显示出推导除了何种型别。

  对于像int这样的平凡型别,从IDE能得到的信息大体良好。不过你很快就会看到,一旦较为复杂的型别现身,IDE显示的信息就不太有用了。

  编译器诊断信息

  想要让编译器显示其推导出的型别,一条有效的途径是使用该型别推导某些编译错误。而报告错误的消息几乎肯定会提及导致该错误的型别。

  

  运行时输出

  Boost的TypeIndex库(常写作Boost.TypeIndex),虽说该库不是C++的一部分,但IDE和像TD这样的模板也不是。Boost库(可从boost.com获得)的好处还不止于此,他跨平台、开源。这样一来,Boost库和那些依赖标准库的代码有几乎同样的可移植性。

  下面介绍一下函数f是如何在使用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; //显示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接受一个型别实参(我们想要获取信息的型别),而且不会移除const、volatile和引用饰词(这也是改模板的名字中为什么含有with_cvr字样),该函数模板返回一个boost::typeindex::type_index对象,它利用成员函数pretty_name产生一个包含人类可读的型别表示的std::string。

std::vector<Widget> createVec();    //工厂函数

const auto vw = createVec();         //使用工厂函数返回值初始化vw

if(!vw.empty()) {
f(&vw[]); //调用f
...
}

  在使用GNU和Clang编译器的情况下,Boost.TypeIndex产生了以下的(精准)输出:

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

  微软编译器取得的结果本质上完全相同:

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

  请记住无论是IDE编译器、编译器错误消息,还是像Boost.TypeIndex这样的库都仅仅是你弄明白你的编译器推导所得型别的辅助工具。他们都十分有用,但是说到底,理解条款1~条款3的型别推导知识这一点无可替代。

要点速记:

1、利用IDE编译器,编译器错误消息、和Boost.TypeIndex库常常能够查看到推导而得的型别。

2、有些工具产生的结果可能会无用,或者不准确。所以,理解C++型别推导规则是必要的。

Effective Modern C++ 条款4:掌握查看型别推导结果的方法的更多相关文章

  1. Effective Modern C++ ——条款6 当auto型别不符合要求时,使用带显式型别的初始化物习惯用法

    类的代理对象 其实这部分内容主要是说明了在STL或者某些其他代码的容器中,在一些代理类的作用下使得最后的返回值并不是想要的结果. 而他的返回值则是类中的一个容器,看下面的一段代码: std::vect ...

  2. Effective Modern C++ 条款2:理解auto型别推导

    在条款1中,我们已经了解了有关模板型别的推导的一切必要知识,那么也就意味着基本上了解了auto型别推导的一切必要知识. 因为,除了一个奇妙的例外情况,auto型别推导就是模板型别推导.尽管和模板型别推 ...

  3. Effective Modern C++ ——条款2 条款3 理解auto型别推导与理解decltype

    条款2.理解auto型别推导 对于auto的型别推导而言,其中大部分情况和模板型别推导是一模一样的.只有一种特例情况. 我们先针对auto和模板型别推导一致的情况进行讨论: //某变量采用auto来声 ...

  4. Effective Modern C++ 条款3:理解decltype

    说起decltype,这是个古灵精怪的东西.对于给定的名字或表达式,decltype能告诉你该名字或表达式的型别.一般来说,它告诉你的结果和你预测的是一样的.不过,偶尔它也会给出某个结果,让你抓耳挠腮 ...

  5. Effective Modern C++ ——条款5 优先选择auto,而非显式型别声明

    条款5 对于auto ,他的好处不仅仅是少打一些字这么简单. 首先在声明的时候, 使用auto会让我们养成初始化的习惯: auto x;//编译不通过必须初始化. 再次对于auto而言,它可以让我们定 ...

  6. Effective Modern C++ ——条款7 在创建对象时注意区分()和{}

    杂项 在本条款的开头书中提到了两个细节性问题: 1.类中成员初始化的时候不能使用小括号. 如: class A { int a(0);//错误 }; 2.对于原子性类别的对象初始化的时候不能使用= 如 ...

  7. 《Effective Modern C++》翻译--条款4:了解怎样查看推导出的类型

    条款4:了解怎样查看推导出的类型 那些想要了解编译器怎样推导出的类型的人通常分为两个阵营. 第一种阵营是实用主义者.他们的动力通常来自于编敲代码过程中(比如他们还在调试解决中),他们利用编译器进行寻找 ...

  8. Effective Modern C++  条款1:理解模板型别推导

    成百上千的程序员都在向函数模板传递实参,并拿到了完全满意的结果,而这些程序员中却有很多对这些函数使用的型别是如何被推导出的过程连最模糊的描述都讲不出来. 但是当模板型别推导规则应用于auto语境时,它 ...

  9. Effective Modern C++翻译(5)-条款4:了解如何观察推导出的类型

    条款4:了解如何观察推导出的类型 那些想要知道编译器推导出的类型的人通常分为两种,第一种是实用主义者,他们的动力通常来自于软件产生的问题(例如他们还在调试解决中),他们利用编译器进行寻找,并相信这个能 ...

随机推荐

  1. Luogu P2484 [SDOI2011]打地鼠(模拟+前缀和)

    P2484 [SDOI2011]打地鼠 题意 题目描述 打地鼠是这样的一个游戏:地面上有一些地鼠洞,地鼠们会不时从洞里探出头来很短时间后又缩回洞中.玩家的目标是在地鼠伸出头时,用锤子砸其头部,砸到的地 ...

  2. 打开串口(COM)号大于9时报错

    使用CreateFile打开串口(COM)号大于9时报错,GetLastError()的值为2. 解决方法: // 把串口名称由 "COMN" 改为 "\\.\COMN& ...

  3. C++ 系列:C++ 内存布局

    1 前言 了解你所使用的编程语言究竟是如何实现的,对于C++程序员可能特别有意义.首先,它可以去除我们对于所使用语言的神秘感,使我们不至于对于编译器干的活感到完全不可思议:尤其重要的是,它使我们在De ...

  4. 性能分析神器VisualVM【转】

    性能分析神器VisualVM[转] Posted on 2015-04-17 09:37 WadeXu 阅读(5809) 评论(6) 编辑 收藏 VisualVM 是一款免费的,集成了多个 JDK 命 ...

  5. 六. Default arguments 参数默认值

    示例: 注意点:函数是会默认声明参数变量的,所以不需要再重新声明一次,否则会报错 错误示例如下: 函数参数的传值方法: 需要注意的是:如果要给第二个参数传值,那第一个参数要传undefined,而不能 ...

  6. jmeter参数化遇到的问题

    遇到的问题是点击运行后,察看结果树没有任何结果,且右上角的警告日志是: meter.threads.JMeterThread: Test failed! java.lang.IllegalArgume ...

  7. leetcode146周赛-1131-绝对值表达式的最大值

    题目描述: class Solution: def maxAbsValExpr(self, arr1, arr2) -> int: def function(s1,s2): result1=[] ...

  8. poj3167- Cow Patterns

    传送门 两个串相等定义为串中每一位排序后的相对大小相等. 一位相等等价于这一位前面比他小的和等于他的数的个数相等. 那么用kmp,比较的时候比较这两个个数就可以了. 一开始很瓜地想,询问一段区间内比我 ...

  9. Linux网桥端口的arp问题

    Linux的brctl addif命令可以将一个接口加入到既有的网桥中,接下来,这个接口就成了brport,属于一个从属的接口,然而你还是可以看到它的,并且可以为它添加IP地址,然后route命令会显 ...

  10. Android基础控件TextView

    1.常用属性 <TextView android:id="@+id/text11" //组件id android:layout_width="match_paren ...