やあ子供たち、夜はまだまだ蒸し暑いね。夜更かしばっかしてないで早く寝ろよ(お前もな)
class Vertex { public: const float& Position( void) const { return _position; } static Vertex* Create( void ){ return new Vertex(); } float _position; }; // //... vector< Vertex* > vv; { vv.resize( 10 ); generate( vv.begin(), vv.end(), Vertex::Create ); } set< float > pos_set;
といった状況があるとき、vvの中のVertexの、_position を、pos_set に詰め込みたい!
for each( Vertex* iv in vv ){ // ←VisualStudioだから pos_set.insert( iv->Position() ); }// iv
でもこう書くと、何がしたいのか理解するのに若干時間がかかる!書き間違いもあるかも知れないし、なんか不安だ!もっと分かりやすく書きたい!しかも一行で!というときに、set の場合は back_inserter() が使えないので、先日の自作NestCallも使ってこんなことしてみるが
for_each( vv.begin(), vv.end(), NestCall( mem_fun( &Vertex::Position ), bind1st( mem_fun1( &set< float >::insert ), &pos_set ) // エラー ) );
set<>::insertの引数は参照なので、もともと参照として引数を受け取るようなファンクタを作成するように作られている、bind1st() は、参照引数を受け取れないので、参照の参照は受け取れませんよーなどというコンパイラの、一見意味不明なメッセージに悩まされることになる。
そこで、そんなときにこれ。
template< class Func, class Para > class my_bind1st_ref_t : public unary_function< typename Func::second_argument_type, typename Func::result_type > { public: typedef typename nurs::remove_modifier < typename Func::second_argument_type >::base_type Vtype; my_bind1st_ref_t( Func func, Para para ) : _func( func ), _para( para ){} result_type operator()( const Vtype& t ) const { return _func( _para, t ); } typedef typename Func::result_type result_type; typedef typename Func::second_argument_type argument_type; Func _func; mutable Para _para; }; template< class Func, class Para > my_bind1st_ref_t< Func, Para > my_bind1st_ref( Func func, Para para ) { return my_bind1st_ref_t< Func, Para >( func, para ); }
(おっと、remove_modifierについてはこちらを参照してくれよな。)
ずばり、参照引数も受け取れる自作bind1stの登場だ。
for_each( vv.begin(), vv.end(),
NestCall( mem_fun( &Vertex::Position ),
my_bind1st_ref( mem_fun1( &set< float >::insert ), &pos_set )
) );
このように、先日のNestCallと組み合わせることで、一行であっさり書けてしまいました。 例によってコード量は増えてるけどね。可読性も下がってる? でもなんかこう書いたほうが安心なのはなぜだろう。へんなこう書かないと気がすまなくなる病気にでもなってしまったのだろうか。最近少し不安だ。