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