我刚刚偶然发现了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只会是rvalue吗?
有谁能帮我找到更多关于这方面的信息吗?
这是否意味着我需要为L和R值编写两个方法重载?
答案
正如Alf的示例所示,函数和类中的t可以是Lvalue或Rvalue。
发布于 2012-09-07 18:15:06
在您的函数中,T是从实际参数中推导出来的。这种特殊组合的主要用途是完美转发。在类模板T中,必须指定它。
例如,这与g++和msvc都编译得很好:
template<class T>
struct S {
S(T&& t){}
};
int main()
{
int i;
S< int& > ss(i);
}发布于 2012-09-07 18:16:39
您在这里处理的是模板参数推导。
通过在不显式定义模板参数的情况下使用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){}
};当然,您可以使用SFINAE方法和模板元编程来确保只有在T和U的基本类型相同的情况下才能实例化构造器模板。
https://stackoverflow.com/questions/12323308
复制相似问题