【模板】模板实参推断和引用

  为了理解如何从函数调用进行类型推断,考虑下面的例子:

template <typename T> void f(T &p);

其中函数参数p是一个模板类型参数T的引用,非常重要的是记住两点:编译器会引用正常的引用绑定规则;const是底层的,不是顶层的。

从左值引用函数参数推断类型

  当一个函数参数是模板类型参数的一个普通(左值)引用时(即,形如T&),绑定规则告诉我们,只能传递给他一个左值(如,一个变量或一个返回引用类型的表达式)。实参可以是const,也可以不是。如果实参是const,则T将被推断为const类型。

template <typename T> void f1(T&); //实参必须是一个左值
//对f1的调用使用实参所引用的类型作为模板参数类型
f1(i);  //i是一个int;模板参数类型T是int
f1(ci); //ci是一个const int;模板参数T是const int
f1(5);  //错误:传递给一个&参数的实参必须是一个左值

  如果一个函数的参数是const T&,正常的绑定规则告诉我们可以传递给它任意类型的实参------一个对象(const或非const)、一个临时对象或一个字面常量值。当函数参数本身是const时,T的推断的结果不会是一个const类型。const已经是函数参数类型的一部分;因此,它不会是模板参数的一部分:

template <typename T> void f2(const T&); //可以接受一个右值
//f2中的参数是const &;实参中的const是无关的
//在每个调用中,f2的参数都被推断为const int&
f2(i);  //i是一个int;模板参数T是int
f2(ci); //ci是一个const int,但模板参数T是int
f2(5);  //一个const int&参数可以绑定到一个右值;T是int

从右值引用函数参数推断类型

  当一个函数参数是右值引用时(即,形如T&&),正常的绑定规则告诉我们可以传递给它一个右值。当我们这样做时,类型推断过程类似普通左值引用函数参数的推断过程。推断出的T类型是该右值的实参类型:

template <typename T> void f3(T&&);
f3(42); //实参是一个int类型的右值;模板参数T是int

引用折叠和右值引用参数

  假定i是一个Int对象,我们可能认为像f3(i)这样的调用是不合法的。毕竟,i是一个左值,而通常我们不能将一个右值引用绑定到一个左值上。但是,C++语言在正常绑定规则之外定义了两个例外规则,允许这种绑定,这两个例外规则是move这种标准库设施正确工作的基础。

  第一个例外规则影响右值引用参数的推断如何进行。当我们将一个左值(如i)传递给函数的右值引用参数,且此右值引用指向模板类型参数(如T&&)时,编译器推断模板类型参数为实参的左值引用类型。因此,当我们调用f3(i)时,编译器推断T的类型为int&,而非int。

  T被推断为int&看起来好像意味着f3的函数参数应该是一个类型int&的右值引用。通常,我们不能(直接)定义一个引用的引用。但是,通过类型别名或通过模板类型参数间接定义是可以的。

  在这种情况下,我们可以使用第二个例外绑定规则:如果我们间接创建一个引用的引用,则这些引用形成了“折叠”。在所有情况下(除了一个例外)

编写接受右值引用参数的函数模板

转载于:https://www.cnblogs.com/bootblack/p/11423986.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值