Item1 Understand template type deduction
2016-08-25 20:39
197 查看
C++的模板对于类型推导来说,在通常情况推导出的类型和我们期望的是一致的,然而事情并不是总是这样如此美妙。例如下面这个例子:
参数类型可以是下面几种情况:
1.
2.
3.
4.
上面的几种情况可以分成三种类型,1和2可以归为引用类型,3是右值引用类型(也可以叫做通用引用类型),4则是类型本身,没有额外的修饰。对于这三种类型来说模板类型推导有着不一样的规则。
Case1: 引用类型
类型推导规则如下:
1. 如果传入的类型是引用类型,那么会忽视掉引用部分,如果是指针类型,则会忽视指针部分
2. 如果传入的类型不是引用类型那么原来是什么类型就推导成什么类型
当参数类型是
对于上面三个变量的类型传递给模板函数f的时候,参数parm的类型会推导成如下:
当参数类型是
当参数类型是
总结一句话,当参数类型是引用类型,那么parm最终的类型就是引用类型。如果有CV限制符,那么parm也会带上CV限制符,如果传入的类型含有引用会发生引用折叠,不会变成
Case2: 右值引用类型
类型推导规则如下:
1. 如果传入的是一个左值,那么会被推导成引用类型
2. 如果传入的是右值,就按照Case1的规则推导
当参数类型是
对于上面三个变量的类型传递给模板函数f的时候,参数
Case3: 类型本身
类型推导规则如下:
1. 如果传入的参数是引用类型,忽视引用部分。
2. 如果不是引用类型,但是带有const,volatile等同样也忽视。
3. 不是引用类型,也没有const volatile修饰符,按照正常规则推导
当参数类型是
对于上面三个变量的类型传递给模板函数f的时候,参数parm的类型会推导成如下:
parm的类型就是传入的类型去掉引用,指针和CV限制符等。
上面的类型推导规则基本上包含了绝大多数模板推导规则,除此之外还有两个类型的推导需要关注。
数组类型参数
数组类型和指针指向一个数组这是两个不同的类型,数组如果传递给函数会退化为指针,因此在模板参数类型的时候,如果参数类型是
函数作为参数
函数作为参数会被退化成函数指针,如果参数类型是
template<typename T> void f(`参数类型` parm);
参数类型可以是下面几种情况:
1.
T&
2.
const T&
3.
T&&
4.
T
上面的几种情况可以分成三种类型,1和2可以归为引用类型,3是右值引用类型(也可以叫做通用引用类型),4则是类型本身,没有额外的修饰。对于这三种类型来说模板类型推导有着不一样的规则。
Case1: 引用类型
类型推导规则如下:
1. 如果传入的类型是引用类型,那么会忽视掉引用部分,如果是指针类型,则会忽视指针部分
2. 如果传入的类型不是引用类型那么原来是什么类型就推导成什么类型
当参数类型是
T&的时候,传入下列三个参数。
int x = 27; const int cx = x; const int& rx= x;
对于上面三个变量的类型传递给模板函数f的时候,参数parm的类型会推导成如下:
x 被推导成 int& //匹配规则2,x被推导成int,因为参数类型是T&,所以就是int& cx 被推导成 const int& //匹配规则2 rx 被推导成 const int& //匹配规则1,被推导成const int&,忽视引用部分,因为参数类型是T&,所以最后就是const int&
当参数类型是
const T&,传入上面三个参数,推导后的类型结果如下:
x 被推导成 const int& cx 被推导成 const int& //const 叠加了 rx 被推导成 const int& //发生了引用折叠
当参数类型是
T*或
const T*的时候本质上和上面的是相同的。当传入一个指针类型,会导致指针折叠。
总结一句话,当参数类型是引用类型,那么parm最终的类型就是引用类型。如果有CV限制符,那么parm也会带上CV限制符,如果传入的类型含有引用会发生引用折叠,不会变成
&&,如果包含cv限制符,也会进行叠加,不会变成
const const。
Case2: 右值引用类型
类型推导规则如下:
1. 如果传入的是一个左值,那么会被推导成引用类型
2. 如果传入的是右值,就按照Case1的规则推导
当参数类型是
T&&,传入下列三个参数:
int x = 27; const int cx = x; const int& rx = x;
对于上面三个变量的类型传递给模板函数f的时候,参数
param的类型会推导成如下:
x 被推导成 int& //匹配规则1,x是左值被推导成引用类型 cx 被推导成 const int& //匹配规则1,cx也是左值,cv限制符会带上。 27 被推导成 int&& //匹配规则2, 27是个右值,T被推导成int,因为参数类型是T&&,所有被推导成int&&
param的类型,取决于传入的变量是否是右值,如果是右值,最终
param的类型就是
&&,有CV限制符就带上。如果是左值那么param的最终类型就是引用类型了。
Case3: 类型本身
类型推导规则如下:
1. 如果传入的参数是引用类型,忽视引用部分。
2. 如果不是引用类型,但是带有const,volatile等同样也忽视。
3. 不是引用类型,也没有const volatile修饰符,按照正常规则推导
当参数类型是
T,传入下列三个参数:
int x = 27; const int cx = x; const int& rx = x;
对于上面三个变量的类型传递给模板函数f的时候,参数parm的类型会推导成如下:
x 被推导成 int //匹配规则3 cx 被推导成 int //匹配规则2 rx 被推导成 int //匹配规则1
parm的类型就是传入的类型去掉引用,指针和CV限制符等。
上面的类型推导规则基本上包含了绝大多数模板推导规则,除此之外还有两个类型的推导需要关注。
数组类型参数
数组类型和指针指向一个数组这是两个不同的类型,数组如果传递给函数会退化为指针,因此在模板参数类型的时候,如果参数类型是
T,那么数组会被推导成指针类型,如果参数类型是
T&,那么数组就会被推导成数组类型,可以使用sizeof求数组的大小。
函数作为参数
函数作为参数会被退化成函数指针,如果参数类型是
T,函数会被推导成一个函数指针,指向这个函数,如果参数类型是
T&,那么函数会被推导成一个引用指向函数的引用。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C++的template模板中class与typename关键字的区别分析
- C与C++之间相互调用实例方法讲解