1

我刚刚在课堂上偶然发现了这一点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 值编写两个方法重载?

答案
正如 Alf 的示例所示,t函数和类中的值可以是左值或右值。

4

2 回答 2

9

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

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

使用类型进行模板参数推导的规则&&是特殊的,以允许完美转发。使用f(i)时,T推导为T&。因此,参数t的类型为T& &&,它折叠为T&。但是,当您使用 时f(42),类型T被推导出为T&&,因此tT&& &&,它折叠为T&&

一旦你强迫 T成为一个特定的类型,所有这些都会有效地消失。崩溃仍然可能发生,但是因为您使用了S<int>, thent将是 type int&&S<int> ss(i)等效于f<int>(i),这也是不合法的。而且由于模板参数推导仅适用于函数而不适用于类型,因此S如果您想要完美的转发,您必须执行以下操作:

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

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

于 2012-09-07T18:16:39.953 回答
2

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

例如,这可以很好地与 g++ 和 msvc 一起编译:

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

int main()
{
    int i;
    S< int& > ss(i);
}
于 2012-09-07T18:15:06.967 回答