您的位置:首页 > 编程语言 > C语言/C++

Item1 Understand template type deduction

2016-08-25 20:39 197 查看
    C++的模板对于类型推导来说,在通常情况推导出的类型和我们期望的是一致的,然而事情并不是总是这样如此美妙。例如下面这个例子:

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++ effective modern-c++