|
想要查看内容赶紧注册登陆吧!
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
C++的模板对于类型推导来说,在通常情况推导出的类型和我们期望的是一致的,然而事情并不是总是这样如此美妙。例如下面这个例子:
- template<typename T>
- void f(`参数类型` parm);
复制代码 参数类型可以是下面几种情况:
1. T&
2. const T&
3. T&&
4. T
上面的几种情况可以分成三种类型,1和2可以归为引用类型,3是右值引用类型(也可以叫做通用引用类型),4则是类型本身,没有额外的修饰。对于这三种类型来说模板类型推导有着不一样的规则。类型推导规则如下:
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。
复制代码
类型推导规则如下:
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的最终类型就是引用类型了。
复制代码
类型推导规则如下:
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&,那么函数会被推导成一个引用指向函数的引用。
|
|