![](/img/trans.png)
[英]Can I typically/always use std::forward instead of std::move?
[英]Do I use std::forward or std::move here?
比方說我有:
template<class T>
struct NodeBase
{
T value;
NodeBase(T &&value)
: value(value) { }
};
我繼承了它:
template<class T>
struct Node : public NodeBase<T>
{
Node(T &&value)
: NodeBase( WHAT_GOES_HERE (value)) { }
};
WHAT_GOES_HERE
應該是std::move
還是std::forward<T>
? 為什么?
因為在Node<T>
的構造函數的實現中,不知道T
是普通類型(即不是引用)還是引用,
std::forward<T>(value)
適合。
只要不知道T &&
是否綁定到右值或左值, std::forward<T>(value)
就是正確的選擇。 這是這種情況,因為在構造函數中我們不知道T &&
是否等同於U &&
對於某些普通類型U
,或等效於U & &&
。
在使用std::forward
或在不同時間確定的函數調用中是否推導出T
並不重要(例如在您的示例中,其中T
是在實例化Node
模板時確定的)。
std::forward<T>(value)
將以與調用者直接調用基類構造函數相同的方式調用繼承的構造函數。 也就是說,當value
是左值時,它將在左value
上調用它,當value
是右值時,它將在右value
上調用它。
可能都沒有。
我懷疑你應該擁有的是:
template<class T>
struct NodeBase
{
T value;
NodeBase(NodeBase &&) = default;
NodeBase(NodeBase const&) = default; // issue: this might not work with a `T&`, but we can conditionally exclude it through some more fancy footwork
NodeBase(NodeBase &) = default;
template<typename U, typename=typename std:enable_if< std::is_convertible<U&&, T>::value >::type >
NodeBase(U &&u)
: value(std::forward<U>(u)) { }
};
template<class T>
struct Node : public NodeBase<T>
{
Node( Node & ) = default;
Node( Node const& ) = default; // issue: this might not work with a `T&`, but we can conditionally exclude it through some more fancy footwork
Node( Node && ) = default;
template<typename U, typename=typename std:enable_if< std::is_convertible<U&&, NodeBase<T>>::value >::type>
Node(U && u)
: NodeBase( std::forward<U>(u) ) { }
};
除非你做的事情非常奇怪。
非常奇怪,這意味着如果你的T
是一個int
,你只想接受移動的值到你的Node
,但是如果你的T
是一個int&
,你只接受非const lvalue int
,如果T
是一個int const&
,您接受任何可轉換為int
值。
這將是一組奇怪的要求放在NodeBase
的構造函數上。 我可以想到可能出現這種情況的情況,但它們並不常見。
假設你只是想讓NodeBase
存儲那些數據,那么在構造函數中使用T&&
是不對的 - 如果你在NodeBase
中存儲一個int
,你可能願意復制那個int
,而不是只接受移動 -來自int
。
上面的代碼就是這樣 - 它允許任何可以存儲在NodeBase
中的NodeBase
傳遞到所述NodeBase
,並具有完美的轉發功能。
另一方面,如果你真的想要一組奇怪的結構限制,那么這對你來說不是正確的答案。 我在構建從通用引用參數構建的template
類型時使用了它,並且我確實想要限制傳入的類型以完全匹配通用引用參數,並且如果參數是rvalue引用則存儲它,並以其他方式保留對它的引用。
在您的示例中沒有推斷出T
T
是類模板參數,而不是函數模板參數。 所以假設你不會將引用類型用作T, T&&
將是對T的rvalue引用,因此它只會綁定到類型為T的rvalues。這些移動是安全的,所以你可以使用std::move
here。
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
}
std::forward
通常僅適用於您具有推導類型的地方,可以是左值引用或右值引用。
template<class T>
void f(T&& x)
{
... std::forward<T>(x) ...
}
因為T&&
實際上可能是左值引用或右值引用。 這只是因為在這種情況下推斷出T
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.