Effective Modern C++ 条款4:掌握查看型别推导结果的方法
采用何种工具来查看型别推导结果,取决于你在软件开发过程的哪个阶段需要该信息。主要研究三个可能的阶段:撰写代码阶段、编译阶段、运行时阶段。
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:掌握查看型别推导结果的方法的更多相关文章
- Effective Modern C++ ——条款6 当auto型别不符合要求时,使用带显式型别的初始化物习惯用法
类的代理对象 其实这部分内容主要是说明了在STL或者某些其他代码的容器中,在一些代理类的作用下使得最后的返回值并不是想要的结果. 而他的返回值则是类中的一个容器,看下面的一段代码: std::vect ...
- Effective Modern C++ 条款2:理解auto型别推导
在条款1中,我们已经了解了有关模板型别的推导的一切必要知识,那么也就意味着基本上了解了auto型别推导的一切必要知识. 因为,除了一个奇妙的例外情况,auto型别推导就是模板型别推导.尽管和模板型别推 ...
- Effective Modern C++ ——条款2 条款3 理解auto型别推导与理解decltype
条款2.理解auto型别推导 对于auto的型别推导而言,其中大部分情况和模板型别推导是一模一样的.只有一种特例情况. 我们先针对auto和模板型别推导一致的情况进行讨论: //某变量采用auto来声 ...
- Effective Modern C++ 条款3:理解decltype
说起decltype,这是个古灵精怪的东西.对于给定的名字或表达式,decltype能告诉你该名字或表达式的型别.一般来说,它告诉你的结果和你预测的是一样的.不过,偶尔它也会给出某个结果,让你抓耳挠腮 ...
- Effective Modern C++ ——条款5 优先选择auto,而非显式型别声明
条款5 对于auto ,他的好处不仅仅是少打一些字这么简单. 首先在声明的时候, 使用auto会让我们养成初始化的习惯: auto x;//编译不通过必须初始化. 再次对于auto而言,它可以让我们定 ...
- Effective Modern C++ ——条款7 在创建对象时注意区分()和{}
杂项 在本条款的开头书中提到了两个细节性问题: 1.类中成员初始化的时候不能使用小括号. 如: class A { int a(0);//错误 }; 2.对于原子性类别的对象初始化的时候不能使用= 如 ...
- 《Effective Modern C++》翻译--条款4:了解怎样查看推导出的类型
条款4:了解怎样查看推导出的类型 那些想要了解编译器怎样推导出的类型的人通常分为两个阵营. 第一种阵营是实用主义者.他们的动力通常来自于编敲代码过程中(比如他们还在调试解决中),他们利用编译器进行寻找 ...
- Effective Modern C++ 条款1:理解模板型别推导
成百上千的程序员都在向函数模板传递实参,并拿到了完全满意的结果,而这些程序员中却有很多对这些函数使用的型别是如何被推导出的过程连最模糊的描述都讲不出来. 但是当模板型别推导规则应用于auto语境时,它 ...
- Effective Modern C++翻译(5)-条款4:了解如何观察推导出的类型
条款4:了解如何观察推导出的类型 那些想要知道编译器推导出的类型的人通常分为两种,第一种是实用主义者,他们的动力通常来自于软件产生的问题(例如他们还在调试解决中),他们利用编译器进行寻找,并相信这个能 ...
随机推荐
- POJ 1127 /// 判断线段与线段是否相交
题目大意: 给定n条线段 接下来n行是端点信息 接下来询问 a b 是否相交 若a与c相交 b与c相交 ,那么a与b就是相交的 先判断任两条线段是否相交 再用folyd #include <cs ...
- CodeForces 258D Little Elephant and Broken Sorting(期望)
CF258D Little Elephant and Broken Sorting 题意 题意翻译 有一个\(1\sim n\)的排列,会进行\(m\)次操作,操作为交换\(a,b\).每次操作都有\ ...
- [笔记]180612 for DevOps
adb devices 识别不了安卓手机:我下的adb interface驱动下载链接:如果设备管理器中ADB Interface是黄色的,就需要先安装adb interface驱动(BD:adb i ...
- bzoj2209 括号序列
题意:给你一个括号序列.操作1:询问需要更改多少个括号使之匹配. 操作2:反转序列,左括号变成右括号. 操作3:翻转序列,倒置. 标程: #include<cstdio> #include ...
- 2016.9.3初中部上午NOIP普及组比赛总结
2016.9.3初中部上午NOIP普及组比赛总结 链接:https://jzoj.net/junior/#contest/home/1339 这次真爽,拿了个第四!(我还被班主任叫过去1小时呢!) 进 ...
- JedisCluster API 整理
windows版redis启动服务器命令:redis-server redis.windows.conf 图表来自菜鸟教程: 列表的操作命令 序号 命令及描述 1 BLPOP key1 [key2 ] ...
- IOS学习笔记57--IOS7状态栏适配(二)
上一遍文章通过XIB的设置达到了状态栏和view重合的问题,这一篇我们讲一讲网传的修改window frame方法. 先上步骤: 第一:在appdeletage里面 添加如下代码: if ( ...
- vue实现分环境打包步骤(给不同的环境配置相对应的打包命令)
在新建好的项目中,一般执行npm run build就是打包了,但此时只能打包到一个环境,不同环境需要配置不同的地址,可以手动更改接口的地址,也可以自行配置命令而不需要每次打包进行地址切换,步骤如下: ...
- js 实现页面局部(或图片)放大功能(vue)
方法: adjustStart1 (e) { e.preventDefault() let event = e.touches if (event.length === 2) { this.style ...
- Maven实战08_仓库
何为Maven仓库 在Maven世界中.任何一个依赖.插件或者项目构建的输出,都可以称之为构件.例如依赖log4j-1.2.15.jar是一个构件,差价maven-compile-plugin-2.0 ...