设foo函数:
template< typename T >
void foo( T&& a ){}
T以下调用将推导出什么类型foo:
foo( 0 ); // is T here int or int&& ?
int a = 0;
foo( a ); // is T here int or int& ?
设foo函数:
template< typename T >
void foo( T&& a ){}
T以下调用将推导出什么类型foo:
foo( 0 ); // is T here int or int&& ?
int a = 0;
foo( a ); // is T here int or int& ?
类型推导的默认规则是引用类型永远不能是推导的结果。鉴于此代码,
template <class T>
void bar(T par);
bar(0);
int a;
bar(a);
int &b;
bar(b);
所有 3 个电话都会打电话foo<int>。即,T推导为int并且par属于 类型int。
转发引用通过简单添加一条规则来工作:当用于转发引用(即deduced的参数)T&&的类型推导的参数是 type 的左值时,使用该类型而不是推导。 TXX &X
请注意,这意味着给定一个 type X,只有X或者X &可以是类型推导的结果;X &&永远不能。
让我们分析您的代码(我将重命名他的函数参数,以明确我所指的内容):
template <class T>
void foo(T &&par);
foo(0);
int a;
foo(a);
在第一种情况下foo(0),参数是类型的右值因此int类型int用于类型推导,这意味着T推导到int(称为 is 的函数foo<int>)和类型par是int &&。
在第二种情况下foo(a),参数是类型的左值int。转发参考规则启动,类型int &用于扣除。T因此推导为int &(函数称为 is foo<int&>),类型par为 " int & &&",可折叠为int &。
推断上下文中的表达式T&&,例如您提供的内容
template< typename T >
void foo( T&& a ){}
即 T 是根据提供的参数推导出来的,受 参考折叠规则的约束。
简而言之;
如果提供的参数是type的左值type,T&&
将展开为type& &&折叠为type&
如果提供的参数是type的右值type,T&&
将扩展为type &&折叠为type&&
注意两者都是引用,如果需要触发另一个函数的右值重载,需要做std::forward<T>(a)
富(0);// 这里的 T 是 int 还是 int&& ?
一个int。
整数a = 0;富(一);// 这里的 T 是 int 还是 int& ?
一个int&。