function8-function+bind
前回function7-placeholder - while( c++ );の続き。
以前function2 - while( c++ );のサンプルを多少修正したfunctionです。
- operator=でcontentの設定
//function.contentが0の場合に投げる例外 class bad_function_call{}; //基本形 template< typename T > class function; //戻り値R、引数2つの特殊化バージョン template< typename R, typename A1, typename A2 > class function< R ( A1, A2 ) > { typedef R result_type; class placeholder { public: virtual ~placeholder(){} virtual result_type invoke( A1, A2 ) = 0; }; template< typename FuncT > class holder : public placeholder { public: FuncT func; public: holder( FuncT const& func ) : func( func ) {} public: result_type invoke( A1 a1, A2 a2 ) { return func( a1, a2 ); } }; private: shared_ptr< placeholder > content; public: template< typename FuncT > function& operator=( FuncT func ) { content = shared_ptr< placeholder >( new holder< FuncT >( func ) ); return *this; } public: result_type operator()( A1 a1, A2 a2 ) { if( !content )throw bad_function_call(); return content->invoke( a1, a2 ); } };
bindが完成したので、メンバ関数の呼び出しも可能なはずです。
前回と同様に以下の3つの関数で試して見ましょう。
int hoge( int x, float y ) { std::cout << "hoge:" << x << "," << y << std::endl; return 1; } struct piyo { int operator()( int x, float y ) { std::cout << "piyo::operator():" << x << "," << y << std::endl; return 2; } }; class fuga { public: int func( int x, float y ) { std::cout << "fuga::func:" << x << "," << y << std::endl; return 3; } };
boostと同じ使い方が出来れば問題ないですよね?
- placeholderが重複しないように、自作したものはnamespace xtlにしています。
- fugaのdeleteを行っていません。
int main() { { xtl::function< int ( int, float ) > f; //グローバル関数 f = hoge; f( 0, 1.0f ); //関数オブジェクト f = piyo(); f( 0, 1.0f ); //メンバ関数 f = xtl::bind( &fuga::func, new fuga, xtl::_1, xtl::_2 ); f( 0, 1.0f ); } { boost::function< int ( int, float ) > f; //グローバル関数 f = hoge; f( 0, 1.0f ); //関数オブジェクト f = piyo(); f( 0, 1.0f ); //メンバ関数 f = boost::bind( &fuga::func, new fuga, _1, _2 ); f( 0, 1.0f ); } return 0; }
実行結果
おおおおおおおお!ちゃんと実行できてますねw
boost::functionに自作bindを渡しても、正しく動作しているようです。
{ boost::function< int ( int, float ) > f; //自作bindでメンバ関数 f = xtl::bind( &fuga::func, new fuga, xtl::_1, xtl::_2 ); f( 0, 1.0f ); }
download
- function_bind20081216.zip
- VC++2008ExpressEdition用