function1
今日はboost::functionについて。
日記を書き始めるきっかけになったものです。
boost::functionの実装のために情報を探していた際、以下のエントリを見つけて感動しました。
ここを見れば、自力で実装できちゃいますね。偉大なる先人の方々に感謝です。
というか中の人は変態ですねw(褒め言葉です)
私も変態プログラマになれるよう気合入れていきますよ。(リンク先の方々はスーパー変態プログラマを超えたスーパー変態プログラマといったところですか?)
さて、本題。
lokiにはfunctorというクラスで同様のものが実装されていますが、正直見た目がよろしくないです。
loki::Functor< int, TYPELIST2( int, float ) > a = func; //int func( int, float );
Functor< ... >のテンプレート引数部分が嫌いです。美しくない。
boostでは以下のように書けます。
boost::function< int ( int, float ) > a = func;
同じ戻りと引数の型であれば、普通の関数、関数オブジェクト、メンバ関数すべて格納できます。しゅごい。。。
C++プログラマならこんなクラスを作ってみたいですよね?ね?
早速作ってみましょう。
タイプリストを使わずに、どのように戻り値と引数の型のセットを渡すのか
単純に書けばこうですね。
しかし、テンプレート引数をTで受け取ると、operator()の型がわかりません。
template< typname T > class function { public: ? operator()( ?, ? ); };
答え。
template< typename T > class function; //戻り値R、引数T1、T2の特殊化バージョン template< typename R, typename T1, typename T2 > class function< R ( T1, T2 ) > { public: R operator()( T1 t1, T2 t2 ); };
卑怯ですね。こんな書き方できるなんて知りませんよ。
これをベースに関数を渡せるように改良しましょう。
template< typename T > class function; //戻り値R、引数T1、T2の特殊化バージョン template< typename R, typename T1, typename T2 > class function< R ( T1, T2 ) > { typedef R result_t; typedef result_t ( func_t )( T1, T2 ); private: func_t* func_ptr; public: template< typename FuncT > function( FuncT func ) : func_ptr( func ) {} public: result_t operator()( T1 t1, T2 t2 ) { return func_ptr( t1, t2 ); } }; int func( int, float ) { return 0; } int main() { function< int ( int, float ) > a( func ); int b = a( 0, 1.0f ); std::cout << b << std::endl; return 0; }
正しくbの値が表示されました。
第1段階突破です。