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

时间:2012-09-07 18:12:01

标签: c++ c++11 rvalue-reference 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  

课堂上:

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&&’

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

ANSWER
正如Alf的例子所示,函数和类中的t可以是Lvalue或Rvalue。

2 个答案:

答案 0 :(得分:9)

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

通过使用f 而不用显式定义模板参数,C ++编译器现在必须从传递它的参数中决定模板参数类型T是什么。

使用&&类型的模板参数推导规则是特殊的,以允许完美转发。当您使用f(i)时,T会被推断为T&。因此,参数t的类型为T& &&,它会折叠为T&。但是,当您使用f(42)时,类型T会被推断为T&&,因此tT&& &&,会折叠为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){}
};

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

答案 1 :(得分:2)

在你的函数中T是从实际参数中推导出来的。该特定组合的主要用途是完美转发。在类模板T中没有推导出来,必须指定它。

例如,这与g ++和msvc很好地编译:

template<class T> 
struct S { 
       S(T&& t){}
};

int main()
{
    int i;
    S< int& > ss(i);
}