T &&在模板化的功能和类中

Leo*_*sky 1 c++ rvalue-reference c++11 pass-by-rvalue-reference

T&&在课堂上偶然发现了它,功能意味着不同的东西.
功能:

template<class T> void f(T&& t){};   // t is R or L-value
...
int i=0; 
f(i);   // t in f is lvalue
f(42);  // t in f is rvalue  
Run Code Online (Sandbox Code Playgroud)

在班上:

template<class T> 
struct S { 
       S(T&& t){}  // t is only R-value? 
};
...
int i;
S<int> ss(i);   // compile error - cannot bind lvalue to ‘int&&’
Run Code Online (Sandbox Code Playgroud)

这是否意味着如果我们T&& t在课堂上,t那么只有rvalue?
有人可以指出我可以获得更多相关信息吗?
这是否意味着我需要为L和R值写两个方法重载?

答案
正如Alf的例子所示,t在函数和类中可以是Lvalue或Rvalue.

Nic*_*las 9

你在这里处理模板参数推断.

通过在f 明确定义模板参数的情况下使用,C++编译器现在必须T从传递它的参数中确定模板参数类型是什么.

模板参数推导与&&类型的规则是特殊的,以允许完美的转发.使用时f(i),T推断为T&.因此,参数t是类型T& &&,其折叠为T&.然而,当你使用f(42),类型T推导的T&&,因此t就是T&& &&,它瓦解成T&&.

一旦你强迫 T成为一种特定的类型,所有这一切都会有效消失.崩溃仍然可能发生,但因为你使用过S<int>,那么t将是类型int&&.S<int> ss(i)实际上相当于f<int>(i),这也是不合法的.并且由于模板参数推导仅适用于函数而不适用于类型,因此S如果您想要完美转发,则必须执行以下操作:

template<class T> 
struct S { 
    template<class U>
    S(U&& t){}
};
Run Code Online (Sandbox Code Playgroud)

当然,您可以使用SFINAE方法和模板元编程来确保构造函数模板只能在基本类型TU相同时实例化.