总结自Effective Modern C++
对于模板的形别推导,通常情况下是符合人类的预期的.
首先先看一些模板的例子,方便后续分情况讨论:
// case 1 templatevoid f(T& param); // 引用 也可以表示为指针 例如 void f(T* param); // case 2 template void f(T&& param); // 万能引用 //case 3 template void f(T param); // 即 不是指针 也 不是引用
有一个大的前提,推导过程会忽略参数的引用性质
推导规则的不同 取决于三种不同的情况:
情况1: param 是一个引用或者指针
这是最简单的推导过程,这个情况下
templatevoid myTemplate1(T& param) { std::cout <<" param = " <(int& param) myTemplate1(cx); // 相当于调用了myTemplate1 (const int& param) myTemplate1(rx); // 相当于调用了myTemplate1 (const int& param) myTemplate1(rccx); // 相当于调用了myTemplate1 (const int * const& param)
和预期一致
换成指针也一样
templatevoid myTemplate2(T* param) { std::cout << " param = " << *param << std::endl; } int* px = &x; const int* pcx = px; // const int &*rpcx = ℞ //不可以有一个类型是指向引用的指针 myTemplate2(px); // 相当于调用了 myTemplate2 (int * param) myTemplate2(pcx); // 相当于调用了 myTemplate2 (const int * param)
注意:
T都被推导为 int 或者 const int
param 会推导为 int& 或者 int*
情况2: param是一个万能引用
首先先说一下万能引用和引用折叠
参数声明为&& 时,就代表这个参数是一个万能引用[ 不是说只能接受右值 ]
&& 和 & 结合 结果为 & 即 [左值]
& 和 && 结合 结果为 & 即 [左值]
& 和 & 结合 结果为 & 即 [左值]
&& 和 && 结合 结果为 && 即 [右值] 唯一一种会得到右值的情况哦
所以 参数写成这样的话,
传入左值,我们的param就推导成左值;
传入右值 我们的param就推导成右值.
有了以上的规则,万能引用的模板推导大致如下:
templatevoid myTemplate3(T&& param) { std::cout << " param = " << *param << std::endl; } int x = 25; const int cx = x; const int& rx = x; myTemplate3(x); // 相当于调用了 myTemplate3 (int & param) myTemplate3(cx); // 相当于调用了 myTemplate3 (const int & param) myTemplate3(rx); // 相当于调用了 myTemplate3 (const int & param) myTemplate3(25); // 相当于调用了 myTemplate3 (int && param)
上面,传入左值, T的形别会被推导为int& 注意,这是唯一一种T被推导为引用的情况! 唯一哦
传入右值 T的形别是int
param被推导的形别也如上,自己看一下吧.



