元記事: http://d.hatena.ne.jp/y_mashiro/20100122/1264102639
↑の記事を見て、なるほど便利だなー、と思いつつも、boost::function を使っている事が気にくわなかったので、 boost::function を使わず静的に全てを決定出来る bind_mem_fn を作ってみました。
元記事の bind_mem_fn とは引数の順序が入れ替わってますが好みの問題なので気にしないでください。あと bind_from_this は多分あっという間に実装できると思うのですが、面倒なので作ってません。あしからず。
#include <boost/call_traits.hpp> #include <boost/mem_fn.hpp> #include <boost/preprocessor.hpp> #include <boost/function_types/result_type.hpp> // 引数の最大値 #ifndef GINTENLIB_ARG_COUNT #define GINTENLIB_ARG_COUNT 10 #endif namespace gintenlib { template<typename Obj, typename Func> struct mem_fn_binder { typedef Func function_type; typedef typename boost::function_types::result_type<Func>::type result_type; Obj obj; Func pf; // 構築 mem_fn_binder( typename boost::call_traits<Obj>::param_type obj_, Func pf_ ) : obj( obj_ ), pf( pf_ ) {} // 無引数バージョン result_type operator()() { return boost::mem_fn( pf )( obj ); } result_type operator()() const { return boost::mem_fn( pf )( obj ); } // 多引数バージョン #define GINTENLIB_GEN_( z, n, const_ ) \ template< BOOST_PP_ENUM_PARAMS( n, typename A ) > \ result_type operator() \ ( BOOST_PP_ENUM_BINARY_PARAMS( n, const A, &arg ) ) const_ \ { \ return boost::mem_fn( pf )( obj, BOOST_PP_ENUM_PARAMS( n, arg ) ); \ } // #define GINTENLIB_GEN_ BOOST_PP_REPEAT_FROM_TO( 1, BOOST_PP_INC(GINTENLIB_ARG_COUNT), GINTENLIB_GEN_, BOOST_PP_EMPTY() ) BOOST_PP_REPEAT_FROM_TO( 1, BOOST_PP_INC(GINTENLIB_ARG_COUNT), GINTENLIB_GEN_, const ) #undef GINTENLIB_GEN_ }; // mem_fn_binder<Obj, Func> // 構築 template<typename Obj, typename Func> mem_fn_binder<Obj, Func> bind_mem_fn( Obj obj, Func pf ) { return mem_fn_binder<Obj, Func>( obj, pf ); } } // namespace gintenlib #include <iostream> #include <boost/format.hpp> using namespace std; using boost::format; struct hoge { void foo() { cout << "foo!\n"; } void bar( int x, int y ) const { cout << format("(%1%, %2%)\n") % x % y; } }; #include <boost/ref.hpp> int main() { using gintenlib::bind_mem_fn; hoge h; // 無引数バージョン // 値 bind_mem_fn( h, &hoge::foo )(); // ポインタ bind_mem_fn( &h, &hoge::foo )(); // 参照( 型指定 version ) bind_mem_fn<hoge&>( h, &hoge::foo )(); // 引数ありバージョン // 値 bind_mem_fn( h, &hoge::bar )( 1, 2 ); // ポインタ bind_mem_fn( &h, &hoge::bar )( 30, 40 ); // 参照( boost::ref version ) bind_mem_fn( boost::ref(h), &hoge::bar )( 23, 42 ); }
出力例:
foo! foo! foo! (1, 2) (30, 40) (23, 42)
こんな感じでどうでしょか?