鍋あり谷あり

テーマを決めずに適当に書いています。

型から推論する

boost::tuple を直接利用しなくてもいいのであれば、
id:mb2sync:20051108:p1
でやっているようなことは、もうちょっと直接的に書くこともできる。
要点だけを書くと:

template< typename t > struct xtuple_base
{
  t m;
  xtuple_base( const t & _m ) : m( _m ){}
  t & get(){  return m;  }
};

template< typename t0, typename t1 > struct xtuple
  : public xtuple_base< t0 >
  , public xtuple_base< t1 >
{
	xtuple( const t0 & _m0, const t1 & _m1 )
	: xtuple_base< t0 >( _m0 )
	, xtuple_base< t1 >( _m1 )
	{}
	xtuple( const t1 & _m1, const t0 & _m0 )
	: xtuple_base< t0 >( _m0 )
	, xtuple_base< t1 >( _m1 )
	{}
	template< typename t >
	t & get(){  return xtuple_base< t >::get(); }
};

void test()
{
	xtuple< int, double > foo( 1, 2.0 );
	xtuple< float, char > bar( 'c', 3.0f ); // テンプレート引数の順序とコンストラクタの引数の順序が違うが、OK。
	xtuple< int, int > baz( 1, 1 ); // コンパイルエラー
	cout << foo.get<int>() << ", " << foo.get<double>() << endl; // -> 1, 2
	cout << bar.get<char>() << ", " << bar.get<float>() << endl; // -> c, 3
}

こんな感じ。
デフォルトコンストラクタとか、コピーコンストラクタとか、const 版の get とか、まだまだ書かなくてはいけないものはたくさんあるけれど。

コンストラクタを2個書いたのは、test() 内で使われているとおり、引数の順序を憶えなくてもよくするため。

上記はテンプレート引数2個のバージョンなのでコンストラクタが2個で済んでいるが、テンプレート引数が増えると、必要なコンストラクタの数が指数関数的に増えてしまう。
テンプレート引数5個なら、コンストラクタが120個になる。うへ。

でも十分便利そうな気がする。どうだろう。