//--------------------------------------------------------------------------- /* クロージャ by Gimite 特定のオブジェクトの特定のメンバ関数の呼び出しを、関数オブジェクトに 変換する。boost::functionと組み合わせると便利。 無項、単項、二項メンバ関数対応。 ex. struct A{ void f(int i){ ... } }; A a; boost::function1 func= gimite::closure(&a, &A::f); func(3); // a.f(3) と等価。 第1引数にはスマートポインタも取れる。ただし、std::auto_ptrの場合は 次のようにして参照を渡す必要が有る。 std::auto_ptr a(new A); gimite::closure&>(a, &A::f); */ //--------------------------------------------------------------------------- #ifndef GIMITE_closureH #define GIMITE_closureH //--------------------------------------------------------------------------- #include #include //--------------------------------------------------------------------------- namespace gimite{ //--------------------------------------------------------------------------- template class nullary_closure_t { public: typedef Result result_type; private: ClassPtr obj; Result (Class::*func)(); public: nullary_closure_t(ClassPtr a_obj, Result (Class::*a_func)()) : obj(a_obj), func(a_func){} Result operator()()const {return ((*obj).*func)();}//(*1) }; template class const_nullary_closure_t { public: typedef Result result_type; private: ClassPtr obj; Result (Class::*func)()const; public: const_nullary_closure_t(ClassPtr a_obj, Result (Class::*a_func)()) : obj(a_obj), func(a_func){} Result operator()()const {return ((*obj).*func)();} }; //*1 BCCでは(obj->*func)()だとスマートポインタを受け入れない。 //--------------------------------------------------------------------------- template inline nullary_closure_t closure(ClassPtr obj, Result (Class::*func)()){ return nullary_closure_t(obj, func); } template inline const_nullary_closure_t closure(ClassPtr obj, Result (Class::*func)()const){ return const_nullary_closure_t(obj, func); } //--------------------------------------------------------------------------- template class unary_closure_t: public std::unary_function { ClassPtr obj; Result (Class::*func)(Arg); public: unary_closure_t(ClassPtr a_obj, Result (Class::*a_func)(Arg)) : obj(a_obj), func(a_func){} Result operator()(boost::call_traits::param_type arg)const {return ((*obj).*func)(arg);} }; template class const_unary_closure_t: public std::unary_function { ClassPtr obj; Result (Class::*func)(Arg)const; public: const_unary_closure_t(ClassPtr a_obj, Result (Class::*a_func)(Arg)const) : obj(a_obj), func(a_func){} Result operator()(boost::call_traits::param_type arg)const {return ((*obj).*func)(arg);} }; //--------------------------------------------------------------------------- template inline unary_closure_t closure(ClassPtr obj, Result (Class::*func)(Arg)){ return unary_closure_t(obj, func); } template inline const_unary_closure_t closure(ClassPtr obj, Result (Class::*func)(Arg)const){ return const_unary_closure_t(obj, func); } //--------------------------------------------------------------------------- template class binary_closure_t: public std::binary_function { ClassPtr obj; Result (Class::*func)(Arg1, Arg2); public: binary_closure_t(ClassPtr a_obj, Result (Class::*a_func)(Arg1, Arg2)) : obj(a_obj), func(a_func){} Result operator()(boost::call_traits::param_type arg1, boost::call_traits::param_type arg2)const {return ((*obj).*func)(arg1, arg2);} }; //--------------------------------------------------------------------------- template class const_binary_closure_t: public std::binary_function { ClassPtr obj; Result (Class::*func)(Arg1, Arg2)const; public: const_binary_closure_t (ClassPtr a_obj, Result (Class::*a_func)(Arg1, Arg2)const) : obj(a_obj), func(a_func){} Result operator()(boost::call_traits::param_type arg1, boost::call_traits::param_type arg2)const {return ((*obj).*func)(arg1, arg2);} }; //--------------------------------------------------------------------------- template inline binary_closure_t closure(ClassPtr obj, Result (Class::*func)(Arg1, Arg2)){ return binary_closure_t(obj, func); } template inline const_binary_closure_t closure(ClassPtr obj, Result (Class::*func)(Arg1, Arg2)const){ return const_binary_closure_t (obj, func); } //--------------------------------------------------------------------------- }//namespace gimite //--------------------------------------------------------------------------- #endif