Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ T&&;在模板化函数和类中_C++_C++11_Rvalue Reference_Pass By Rvalue Reference - Fatal编程技术网

C++ T&&;在模板化函数和类中

C++ T&&;在模板化函数和类中,c++,c++11,rvalue-reference,pass-by-rvalue-reference,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 void f(T&&T){};//t是R或L值 ... int i=0; f(i);//f中的t是左值 f(42);//f中的t

我刚刚偶然发现,
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 void f(T&&T){};//t是R或L值
...
int i=0;
f(i);//f中的t是左值
f(42);//f中的t是右值
课堂上:

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&&’
模板
结构S{
S(T&&T){}//T是唯一的R值吗?
};
...
int i;
S ss(i);//编译错误-无法将左值绑定到“int&&”
这是否意味着如果我们在课堂上有
T&&T
,那么
T
只会是右值?
有人能告诉我在哪里可以得到更多的信息吗?
这是否意味着我需要为L和R值编写两个方法重载

回答

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

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

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

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

int main()
{
    int i;
    S< int& > ss(i);
}
模板
结构S{
S(T&&T){}
};
int main()
{
int i;
Sss(i);
}

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

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

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

int main()
{
    int i;
    S< int& > ss(i);
}
模板
结构S{
S(T&&T){}
};
int main()
{
int i;
Sss(i);
}

这里处理的是模板参数推断

通过使用<代码> f <代码>而不显式定义模板参数,C++编译器现在必须决定模板参数类型<代码> t>代码>是从您传递的参数中得出的。 使用

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

一旦你强迫
T
成为一个特定的类型,所有这些实际上都消失了。折叠仍然可能发生,但由于使用了
S
,因此
t
的类型将为
int&
S ss(i)
实际上等同于
f(i)
,这也是不合法的。由于模板参数推导只适用于函数而不适用于类型,因此如果您想要完美的转发,您必须对
S
执行以下操作:

template<class T> 
struct S { 
    template<class U>
    S(U&& t){}
};
模板
结构S{
样板
S(U&t){}
};

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

这里处理的是模板参数推断

通过使用<代码> f <代码>而不显式定义模板参数,C++编译器现在必须决定模板参数类型<代码> t>代码>是从您传递的参数中得出的。 使用

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

一旦你强迫
T
成为一个特定的类型,所有这些实际上都消失了。折叠仍然可能发生,但由于使用了
S
,因此
t
的类型将为
int&
S ss(i)
实际上等同于
f(i)
,这也是不合法的。由于模板参数推导只适用于函数而不适用于类型,因此如果您想要完美的转发,您必须对
S
执行以下操作:

template<class T> 
struct S { 
    template<class U>
    S(U&& t){}
};
模板
结构S{
样板
S(U&t){}
};

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

T
可以是右值引用或左值引用,但在这两种情况下,
T
都是左值。无论类型如何,每个函数参数都是左值。
t
可以是右值引用或左值引用,但在这两种情况下,
t
都是左值。无论类型如何,每个函数参数都是左值。