模板类型推导、auto推导
effective modern c++ 果然是神书,干货满满,简单记录下。
item1 模板推倒
典型的模板函数
temlate<class T>
void fn(ParamType param)
| 要记住的东西 |
|---|
| 在模板类型推导的时候,有引用特性的参数的引用特性会被忽略 |
| 在推导通用引用参数的时候,左值会被特殊处理 |
在推导按值传递的参数时候,const和/或volatile参数会被视为非const和非volatile |
| 在模板类型推导的时候,参数如果是数组或者函数名称,他们会被退化成指针,除非是用在初始化引用类型 |
当ParamType 是指针或者引用时,
如果
expr的类型是个引用,忽略引用的部分。然后利用
expr的类型和ParamType对比去判断T的类型。
template<typename T>
void f(T& param); // param是一个引用类型 int x = ; // x是一个int
const int cx = x; // cx是一个const int
const int& rx = x; // rx是const int的引用 f(x); // T是int,param的类型时int& f(cx); // T是const int,
// param的类型是const int&
f(rx); // T是const int
// param的类型时const int&
当ParamType 是右值引用时,(注意到param是左值时的特殊性)
如果
expr是一个左值,T和ParamType都会被推导成左值引用。这有些不同寻常。第一,这是模板类型T被推导成一个引用的唯一情况。第二,尽管ParamType利用右值引用的语法来进行推导,但是他最终推导出来的类型是左值引用。如果
expr是一个右值,那么就执行“普通”的法则(第一种情况)
template<typename T>
void f(T&& param); // param现在是一个通用的引用 int x = ; // 和之前一样
const int cx = x; // 和之前一样
const int& rx = x; // 和之前一样 f(x); // x是左值,所以T是int&
// param的类型也是int& f(cx); // cx是左值,所以T是const int&
// param的类型也是const int& f(rx); // rx是左值,所以T是const int&
// param的类型也是const int& f(); // 27是右值,所以T是int
// 所以param的类型是int&&
当ParamType 既不是指针也不是引用时,按照pass by value 来
和之前一样,如果
expr的类型是个引用,将会忽略引用的部分。如果在忽略
expr的引用特性,expr是个const的,也要忽略掉const。如果是volatile,照样也要忽略掉(volatile对象并不常见。它们常常被用在实现设备驱动上面。查看更多的细节,请参考条款40。)
int x = ; // 和之前一样
const int cx = x; // 和之前一样
const int& rx = x; // 和之前一样 f(x); // T和param的类型都是int f(cx); // T和param的类型也都是int f(rx); // T和param的类型还都是int
最后再来个大杀器
//数组的引用再理解下
//int a[]={1,2,3} --> a的类型是啥? int [3]
//int & rb --->rb的类型是啥? rb先与&结合,表明是个引用,然后接触int 表明是个int型的引用
//int (&ra)[]={1,2,3} -->ra的类型是啥? ra先与&结合,表明是个引用,然后接触 int [3] 是个int [3] 的引用
//那如果去掉ra的形参,如何写呢 int (&) [3] ,这是个类型,并且是int [3] 的引用 //计算数组长度 constexpr需要vs2015以上
template<class T, std::size_t SIZE>
constexpr std::size_t ConstArraySize(T(&)[SIZE])
{
return SIZE;
} template<class T, std::size_t SIZE>
std::size_t ArraySize(T(&)[SIZE])
{
return SIZE;
}
item2 auto 推导
能够理解item1的话,这个就好办了,这个和item1的推导几乎一模一样。
item1的关键有个T 和ParamType 需要推导,对于auto来说,T就是auto!这么说有点困难,我们例子来说明
auto x = 27; //T 是auto ParamType也是auto 即item1上的规则3,pass by value
const auto cx = x; //T 是auto ParamType是 const auto ,按照规则3
auto& rx = x; //T 是auto ParamType是 auto & 按照规则1
auto&& uref1 = x; // x是int并且是左值
// 所以uref1的类型是int& auto&& uref2 = cx; // cx是int并且是左值
// 所以uref2的类型是const int& auto&& uref3 = ; // 27是int并且是右值
// 所以uref3的类型是int&& const char name[] = // name的类型是const char[13]
"R. N. Briggs"; auto arr1 = name; // arr1的类型是const char* auto& arr2 = name; // arr2的类型是const char (&)[13] void someFunc(int, double); // someFunc是一个函数,类型是
// void (*)(int, double) auto& func2 = someFunc; // func1的类型是
// void (&)(int, double)
到此为止,我们都非常成功,接下来是auto 与模板推导不同的地方
auto x1 = ; // 类型时int,值是27
auto x2(); // 同上
auto x3 = { }; // 类型是std::intializer_list<int>
// 值是{ 27 }
auto x4{ }; // 同上
auto x5 = { , , 3.0 }; // 错误! 不能讲T推导成
// std::intializer_list<T>
auto x = { , , }; // x的类型是
// std::initializer_list<int>
template<typename T> // 和x的声明等价的
void f(T param); // 模板
f({ , , }); // 错误的!没办法推导T的类型
template<typename T>
void f(std::initializer_list<T> initList);
f({ , , }); // T被推导成int,initList的
// 类型是std::initializer_list<int>
| 要记住的东西 |
|---|
auto类型推导通常和模板类型推导类似,但是auto类型推导假定花括号初始化代表的类型是std::initializer_list,但是模板类型推导却不是这样 |
auto在函数返回值或者lambda参数里面执行模板的类型推导,而不是通常意义的auto类型推导 |
模板类型推导、auto推导的更多相关文章
- C++11 - 类型推导auto关键字
在C++11中,auto关键字被作为类型自动类型推导关键字 (1)基本用法 C++98:类型 变量名 = 初值; int i = 10; C++11:auto 变量名 = 初值; auto i ...
- Effective Modern C++翻译(7)-条款6:当auto推导出意外的类型时,使用显式的类型初始化语义
条款6:当auto推导出意外的类型时,使用显式的类型初始化语义 条款5解释了使用auto来声明变量比使用精确的类型声明多了了很多的技术优势,但有的时候,当你想要zag的时候,auto可能会推导出了zi ...
- C++ 11 学习1:类型自动推导 auto和decltype
Cocos 3.x 用了大量的C++ 11 的东西,所以作为一个C++忠实粉丝,有必要对C++ 11进行一个系统的学习. 使用C++11之前,一定要注意自己使用的编译器对C++11的支持情况,有些编译 ...
- Effective Modern C++翻译(2)-条款1:明白模板类型推导
第一章 类型推导 C++98有一套单一的类型推导的规则:用来推导函数模板,C++11轻微的修改了这些规则并且增加了两个,一个用于auto,一个用于decltype,接着C++14扩展了auto和dec ...
- item 6: 当auto推导出一个不想要的类型时,使用显式类型初始化的语法
本文翻译自<effective modern C++>,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 Item 5解释了比起显式指定类型,使用auto来 ...
- C++11 类型推导auto
在C++11之前,auto关键字用来指定存储期.在新标准中,它的功能变为类型推断.auto现在成了一个类型的占位符,通知编译器去根据初始化代码推断所声明变量的真实类型.使用auto会拖慢c++效率吗? ...
- C++11 自动推导auto
C++11 自动推导auto C++11中引入的auto主要有两种用途:自动类型推导和返回值占位. auto在C++98中的标识临时变量的语义,由于使用极少且多余,在C++11中已被删除.前后两个标准 ...
- C++隐式推导-auto关键词
总述 C++中有一个关键字,它不进行显式声明,而进行隐式推导,auto可以在声明变量时根据变量初始值的类型自动为此变量选择匹配的类型.C++语言类似的关键字还有decltype. 如何评价 C++ 1 ...
- 现代C++之理解模板类型推断(template type deduction)
理解模板类型推断(template type deduction) 我们往往不能理解一个复杂的系统是如何运作的,但是却知道这个系统能够做什么.C++的模板类型推断便是如此,把参数传递到模板函数往往能让 ...
随机推荐
- 喜大普奔 | 微信小程序支持PC端打开了
微信小程序可以在PC端打开啦 微信PC版发布了v2.7.0测试版,其中一个重磅的功能就是:支持打开聊天中分享的小程序 咖啡君这么喜欢尝鲜的人自然是在第一时间下载进行了体验 安装成功,会有功能更新说明 ...
- 自己学习并保存的一些shell命令
摘要: 在学习过程中,不免会遇到有些命令,那种需要的,但是你没有掌握的命令.为了节省时间,担心忘记这些,特开辟这个随笔,随时记录用到的一些命令.那么常用的不提了,自己去收集吧~ 1.文件按日期排序 应 ...
- 看完这篇还不清楚Netty的内存管理,那我就哭了!
说明 在学习Netty的时候,ByteBuf随处可见,但是如何高效分配ByteBuf还是很复杂的,Netty的池化内存分配这块还是比较难的,很多人学习过,看过但是还是云里雾里的,本篇文章就是主要来讲解 ...
- HTML/CSS:div居中和div内部元素垂直居中(1)
div居中 div水平和垂直居中,text-align和vertical-align不起作用,因为标签div没有这两个属性,所以再css中设置这两个值不能居中的效果 1. div水平居中:设置marg ...
- Pipeline 模型
解决的问题 解决并发效率问题,将任务拆分成流水线,然后多线程并发执行,比之单线程执行快. 案例 CPU 流水线 Tomcat 容器 Structs
- net core Webapi基础工程搭建(一)——开发工具及环境
目录 开发工具 版本 后端框架 开发工具 Visual Studio 2019,既然要折腾那就体验最新版的开发工具有什么特殊的地方,之前个人开发使用的是2017. 下载地址:https://visua ...
- error LNK2001: unresolved external symbol "__declspec(dllimport)
作为C++的小白,出现这个错误,是最头痛的.针对这种问题,我搜了网上的相关答案,很多都是在教Project ---> Settings中改动相关设置.我改了之后,问题依旧没有解决.后面查了这种问 ...
- SQL Server发布订阅报错:The conversion of a datetime data type to smalldatetime data type resulted in an out of range value.
执行SQL Server发布订阅时,报错如下信息: The conversion of a datetime data type to smalldatetime data type resulted ...
- 聊聊我在这家公司设计的SSO
最近小明遇到一个需求:需要将几个独立的系统(子系统)汇总到一个集中的系统(父系统)当中,当用户在父系统登录过后,再点击这几个子系统,就可以免登录跳转到任意一个系统.当时一听,duang~duang~就 ...
- Okhttp3源码解析(2)-Request分析
### 前言 前面我们讲了 [Okhttp的基本用法](https://www.jianshu.com/p/8e404d9c160f) [Okhttp3源码解析(1)-OkHttpClient分析]( ...