3

次のパターンが発生する (C++98) プログラムを作成しようとしています: 非常に単純な汎用タプル クラスがあり、ファクトリを使用して構築された値で埋める必要があります。最小限のサンプル コードは次のとおりです。

#include <iostream>

class diagnostics
{
private:
  int payload;
public:
  diagnostics(int a)
    : payload(a)
  {
    std::cout << "constructor\n";
  }

  diagnostics(const diagnostics& o)
    : payload(o.payload)
  {
    std::cout << "copy constructor\n";
  }

  ~diagnostics()
  {
    std::cout << "destructor [" << payload << "]\n";
  }
};

struct creator
{
  static diagnostics create()
  {
    static int i = 0;
    return diagnostics(++i);
  }
};

template<class Head, class Tail>
struct tuple
{
  Head head;
  Tail tail;
  typedef Head head_t;
  typedef Tail tail_t;

  tuple(const Head& h, const Tail& t)
    : head(h), tail(t)
  {
  }
};
struct empty_tuple { };

template<class Tuple, class Create>
struct create_helper
{
  static Tuple create()
  {
    return Tuple(Create::create(),
        create_helper<typename Tuple::tail_t, Create>::create());
  }
};
template<class Create>
struct create_helper<empty_tuple, Create>
{
  static empty_tuple create()
  {
    return empty_tuple();
  }
};
template<class Tuple, class Create>
Tuple create()
{
  //return Tuple(Create::create(), empty_tuple()); //(*)
  return create_helper<Tuple, Create>::create();
}

int main()
{
  typedef tuple<diagnostics, empty_tuple> tuple_t;
  tuple_t a = create<tuple_t, creator>();
}

出力は

constructor
copy constructor
destructor [1]
destructor [1]

真ん中の2行をなくしたいです。

説明を簡単にするために、上記のコードで (*) とマークされた行のコメントを外すことができます。これは汎用性を壊しますが、プログラムは壊しません。

ここで私の主な質問に移ります:どうすればこの状況を解決できますか? RVO を防止する標準の何かがありますか (おそらく RVO はここで再帰的に実行する必要があります)。そうでない場合、コンパイラが十分ではないことを受け入れて、これを明示的な方法で発生させる方法はありますか? create() の呼び出し側を複雑にすることは問題ありませんが、タプル内のオブジェクトを複雑にしたくありません (特に、それらのいくつかはデフォルトで構築できず、追加の「初期化」を導入したくありません)。それらに状態)。新しい多分助けを設置できますか?

次の質問は関連しているように見えますが、最終的には役に立ちませんでした: RVO がここで発生しないのはなぜですか? )

4

1 に答える 1

2

5 分後に自分の質問に答えるのは少しばかげているように感じますが、これは次の情報を理解するための最も適切な方法のようです。

これが1つの解決策です。作成コードをタプル クラス自体に転送できます。

struct FILLIT { };

template<class Head, class Tail>
struct tuple
{
  Head head;
  Tail tail;
  typedef Head head_t;
  typedef Tail tail_t;

  tuple(const Head& h, const Tail& t)
    : head(h), tail(t)
  {
  }

  tuple(const tuple& o)
    : head(o.head), tail(o.tail)
  {
    std::cout << "tuple copy\n";
  }

  template<class Create>
  tuple(FILLIT, Create c)
      : head(Create::create()), tail(FILLIT(), c)
  {
  }
};
struct empty_tuple
{
  empty_tuple() {};
  template<class C>
  empty_tuple(FILLIT, C) {};
};

create の互換性のある実装は次のとおりです。

template<class Tuple, class Create>
Tuple create()
{
  return Tuple(FILLIT(), Create());
}

私はまだ他の方法に興味があります。

于 2013-07-30T13:24:33.250 に答える