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個になる。うへ。
でも十分便利そうな気がする。どうだろう。