簡體   English   中英

我在這里使用std :: forward或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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM