次のパターンが発生する (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 がここで発生しないのはなぜですか? )