Meh*_*dad 10 c++ rvalue-reference move-semantics c++11
比方说我有:
template<class T>
struct NodeBase
{
T value;
NodeBase(T &&value)
: value(value) { }
};
Run Code Online (Sandbox Code Playgroud)
我继承了它:
template<class T>
struct Node : public NodeBase<T>
{
Node(T &&value)
: NodeBase( WHAT_GOES_HERE (value)) { }
};
Run Code Online (Sandbox Code Playgroud)
应该WHAT_GOES_HERE
是std::move
和std::forward<T>
?为什么?
因为在构造函数的实现中,Node<T>
不知道T
是普通类型(即不是引用)还是引用,
std::forward<T>(value)
Run Code Online (Sandbox Code Playgroud)
适合.
std::forward<T>(value)
每当不知道是否T &&
绑定到右值或左值时,它是正确的选择.这是这种情况,因为在构造函数中我们不知道是否T &&
等效U &&
于某些普通类型U
,或等效于U & &&
.
T
在函数调用中推断是否std::forward
在不同时间使用或确定(例如在您的示例中,在实例化模板T
时确定的位置Node
)并不重要.
std::forward<T>(value)
将调用继承的构造函数,就像调用者直接调用基类构造函数一样.也就是说,当它value
是一个左值时,它会在左值上调用它,而在右值时它将在左值上调用它value
.
T
在你的例子中没有推导出来。是T
类模板参数,而不是函数模板参数。因此,假设您不会使用引用类型作为 T,T&&
它将是对 T 的右值引用,因此它只会绑定到类型 T 的右值。这些可以安全移动,因此您可以std::move
在此处使用。
template<class T>
struct Node : public NodeBase<T>
{
Node(T &&value)
: NodeBase( std::move (value)) { }
};
int main()
{
int i = 3;
Node<int> x(42); // ok
Node<int> y(std::move(i)); // ok
Node<int> z(i); // error
}
Run Code Online (Sandbox Code Playgroud)
std::forward
通常仅适用于具有推导类型的地方,该推导类型可以是左值引用或右值引用。
template<class T>
void f(T&& x)
{
... std::forward<T>(x) ...
}
Run Code Online (Sandbox Code Playgroud)
因为T&&
实际上可能是左值引用或右值引用。这只是因为T
是在这种背景下推论出来的。