为何传入lvalue reference调用wrapper模板会触发foo的rvalue reference重载?
为何传入左值引用调用wrapper模板会触发foo的右值引用重载?
先看你提供的代码:
#include <iostream> #include <utility> using namespace std; void foo(int&& a){ cout<<"foo&&"<<endl; } void foo(int& a){ cout<<"foo&"<<endl; } template <typename T> void wrapper(T&& a){ cout<<"wrapperTemplate"<<endl; foo(forward<T>(a)); }; int main() { double&& a=5; double& t=a; wrapper(t); }
运行后输出:
wrapperTemplate foo&&
核心原因拆解
这个现象是模板转发引用推导和隐式类型转换规则共同作用的结果:
模板参数推导与引用折叠
wrapper的参数T&& a属于转发引用(万能引用),当传入左值t(类型为double&)时,模板参数T会被推导为double&。根据C++的引用折叠规则,double& &&会直接折叠为double&,因此wrapper内部的a实际是double&类型的左值引用。std::forward的行为
std::forward<T>(a)中T的类型是double&,所以forward会保留a的左值属性,最终传递给foo的是一个double类型的左值。关键:隐式转换产生临时右值
但foo的重载仅接受int&或int&&参数,这里需要把double左值转换为int类型。这个转换过程会生成一个临时的int对象——临时对象属于右值,无法绑定到非const的int&左值引用,但可以绑定到int&&右值引用,因此最终触发了foo(int&&)的重载。
内容的提问来源于stack exchange,提问作者Yasha Shampur
相关产品推荐
相关产品推荐

