10

私が持っているとしましょう:

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>なんで?

4

3 に答える 3

6

コンストラクターの実装では、それがプレーンな型 (つまり、参照ではない) なのか参照なのNode<T>か不明であるため、T

std::forward<T>(value)

適しています。

std::forward<T>(value)T &&が右辺値または左辺値のどちらにバインドされるかがわからないときはいつでも正しい選択です。これは、コンストラクターでは、 が単純なタイプの と同等なのかT &&、 と同等なのかがわからないためです。U &&UU & &&

Tを使用する関数呼び出しで推定されるか、別の時点で決定されるかは問題ではありませんstd::forward(たとえば、テンプレートがインスタンス化Tされたときに決定される場所)。Node

std::forward<T>(value)基本クラスのコンストラクターが呼び出し元によって直接呼び出された場合と同じ方法で、継承されたコンストラクターを呼び出します。つまり、 が左辺値の場合valueは左辺値で、 が右辺値の場合valueは右辺値で呼び出します。

于 2013-06-28T01:52:02.587 に答える
4

おそらくどちらでもない。

あなたが持っているべきだと思うものは次のとおりです。

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が、 が の場合、非 const 左辺値のみを受け入れ、Tがの場合、変換可能な任意の値を受け入れることを意味します。.int&intTint const&int

これは、 のコンストラクターに配置する奇妙な一連の要件になりますNodeBase。これが当てはまる状況を考えることはできますが、一般的ではありません。

NodeBaseそのデータを単に保存したいだけだと仮定するとT&&、コンストラクターを取り込むことは正しいことではありません。intinを保存している場合は、moved-from のみを受け入れるのではなく、NodeBaseそのコピーを作成することをいとわないでしょう。intint

上記のコードはまさにそれを行います。これにより、 に保存できるものはすべて、完全に転送NodeBaseされて、 said に渡されます。NodeBase

一方、実際に奇妙な一連の構築制限が必要な場合、これは正しい答えではありません。ユニバーサル参照引数から構築された型を構築するときにそれを使用しましたがtemplate、渡された型をユニバーサル参照引数と正確に一致するように制限し、引数が右辺値参照である場合はそれを保存したかったのですが、それ以外の場合は、それへの参照を保持します。

于 2013-06-28T02:25:24.953 に答える