模板实参推断过程中允许对函数实参进行的两种类型转换:
(1) const 转换:可以将一个非const对象的引用(或指针)传递给一个const的引用(或指针)形参。
(2)数组或函数指针转换:如果函数形参不是引用类型,则可以对数组或函数类型的实参应用正常的指针转换。一个数组实参可以转换为一个指向其首元素的指针。类似的,一个函数实参可以转换为一个函数类型的指针。
函数模板可以由用普通类型定义的参数。
指定显式模板实参:
//编译器无法推断T1,它未出现在函数参数列表中
template <typename T1, typename T2, typename T3>
T1 sum(T2,T3);
//T1是显式指定的,T2和T3是函数实参类型推断的。
auto val3=sum<long long>(i, lng);//long long sum(int,long)
尾置返回类型与类型转换:
为了获得元素类型,我们可以使用标准库的类型转换模板。
例子:
当参数是一个函数模板实例的地址时,程序上下文必须满足:对每个模板参数,能唯一确定其类型或值。
从左值引用函数参数推断类型:
当一个函数参数是模板类型参数的一个普通(左值)引用时,绑定规则告诉我们,只能传递给它一个左值。实参可以是const类型,也可以不是。如果实参是const,则T被推断成const类型.
如果一个函数参数的类型是const T&,正常的绑定规则告诉我们可以传递它任何类型的实参–一个对象,一个临时对象或是一个字面常量值。当函数参数本身是const时,T的类型推断的结果不会是一个const类型。const已经是函数参数类型的一部分:因此,它不会也是模板参数类型的一部分。
从右值引用函数参数推断类型:
当一个函数参数是一个右值引用时,正常绑定规则告诉我们可以传递给它一个右值。推断出的T的类型是该右值实参的类型:
template <typename T> void f3(T&&);
f3(42);//实参是一个int类型的右值;模板参数T是int
c++语言正常绑定两个例外规则:
(1)当我们将一个左值(i)传递给函数的右值引用参数,且此右值引用指向模板类型参数(T&&),编译器推断模板类型参数为实参的左值引用类型。
(2)如果我们直接创建一个引用的引用,则这些引用形成了“折叠”。在所有情况下(除了一个例外),引用会折叠成一个普通的左值引用类型。在新标准中,折叠规则则扩展到右值引用。只有一种特殊情况会折叠成右值引用:右值引用的右值引用。即
(1)X& &,X& &&和X&& &都折叠成类型X&
(2)类型X&& &&折叠成X&&