template<typename T> void f1(T&);
实参可以是左值、const类型的左值,不能是右值。
f1(i); // 正确,i是int型,T是int
f1(c); // 正确,i是const int 型,T是const int
f1(5); // 错误
template<typename T> void f1(const T&);
实参可以是左值、const类型的左值、右值。
f1(i); // 正确,i是int型,T是int
f1(c); // 正确,c是const int 型,T是int
f1(5); // 正确,5是int&&,T是int
template<typename T> void f1(T&&);
我们可能认为给这种情况传递一个左值给f1是不合法的,但实际上这是合法的,这种情况的实参可以是左值(或左值引用)(无论有无const)、右值(或右值引用)。
1. 当实参是右值(或右值引用)的时候,T被推断为X
f1(5); // 正确,5是int&&型,T是 int
2. 例外规则①:当模板参数是右值(T&&)而实参是左值(或左值引用),也合法,此时T被推断为X&
f1(i); // 正确,i是int型,按照上面的规则,T是 int&
第1种情况我们很容易理解,因为类型完全匹配。
对于第2种情况,根据例外规则①,把T代入,这个f1模板被实例化为 f1(int& &&) ,它的参数是引用的引用,那为啥我们实际传入的是 int& 咧?对于这种情况,实际上是c++有第2条例外规则:引用折叠。
例外规则②:引用折叠(当出现引用的引用类型变量时就会发生引用折叠)
X& &、X& &&、X&& & 这三种等价折叠为 X&
X&& && 等价折叠为 X&&
所以对于 f1(int& &&) ,它等价于 f1(int &),因此我们传入 int& 的实参是可以的。
标签:f1,const,int,折叠,左值,c++,引用,&&,模板 From: https://www.cnblogs.com/tan-wm/p/17437091.html