もはやBoost.ScopeExit・・・
#include <iostream> #include <boost/typeof/typeof.hpp> #include <boost/preprocessor/seq/cat.hpp> #include <boost/preprocessor/seq/for_each_i.hpp> // Steven Watanabe's trick namespace closure { namespace args { template<int> struct declare; typedef void* declared; struct undeclared { declared dummy[2]; }; template<> struct declare<sizeof(undeclared)> { template<int> struct apply { declared value; friend void operator>(bool, const apply&) {} }; }; template<> struct declare<sizeof(declared)> { static const int apply = 0; }; } } extern closure::args::undeclared closure_args; // undefined #define PP_SEQ_TYPE(r, id, i, var)\ BOOST_PP_SEQ_CAT( (closure_args_t_)(i)(_)(id) ) & var; #define PP_SEQ_CLOSURE_TAG_DECL(r, id, i, var) \ typedef BOOST_TYPEOF(var) BOOST_PP_SEQ_CAT( (closure_args_t_)(i)(_)(id) ) ; #define PP_SEQ_CAPUTURE(r, idty, i, var)\ BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2,1,idty) var #define PP_SEQ_CAPUTURE_DECL_T(r, id, i, var)\ BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2,1,(id,BOOST_PP_EMPTY()))\ BOOST_PP_SEQ_CAT( (closure_args_t_)(i)(_)(id) ) & BOOST_PP_CAT(var,i) #define PP_SEQ_CAPUTURE_DECL(r, idty, i, var)\ BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2,1,idty) var( BOOST_PP_CAT(var,i) ) #define PP_SEQ_CAPUTURE_T_DECL(r, idty, i, var)\ BOOST_PP_COMMA_IF(i) BOOST_PP_TUPLE_ELEM(2,1,idty) var(args_ptr->var) #define CLOSURE_START(seq) CLOSURE_START_FORWARD(seq,__LINE__, BOOST_PP_EMPTY()) #define CLOSURE_START_FORWARD(seq,id,ty) CLOSURE_START_T(seq,id,ty) #define CLOSURE_START_T(seq,id,ty) \ BOOST_PP_SEQ_FOR_EACH_I( PP_SEQ_CLOSURE_TAG_DECL,id,seq ) \ struct BOOST_PP_CAT(start_closure_args_t_,id) { \ BOOST_PP_SEQ_FOR_EACH_I( PP_SEQ_TYPE,id,seq ) \ BOOST_PP_CAT(start_closure_args_t_,id)( \ BOOST_PP_SEQ_FOR_EACH_I(PP_SEQ_CAPUTURE_DECL_T, id, seq) \ ) \ : BOOST_PP_SEQ_FOR_EACH_I(PP_SEQ_CAPUTURE_DECL, (id,ty), seq) {} \ } BOOST_PP_CAT(closure_args_value_,id) ( \ BOOST_PP_SEQ_FOR_EACH_I(PP_SEQ_CAPUTURE, (id,ty), seq) \ ); \ closure::args::declare<sizeof(closure_args)> \ ::apply<0> closure_args; \ closure_args.value = &BOOST_PP_CAT(closure_args_value_,id); \ struct start_closure_t_##id { \ BOOST_PP_CAT(start_closure_args_t_,id)* args_ptr; \ BOOST_PP_SEQ_FOR_EACH_I( PP_SEQ_TYPE,id,seq ) \ start_closure_t_##id( void* args ) \ : args_ptr((BOOST_PP_CAT(start_closure_args_t_,id)*)args) \ , BOOST_PP_SEQ_FOR_EACH_I(PP_SEQ_CAPUTURE_T_DECL, (id,ty), seq) {} #define CLOSURE_END(name) } name( closure_args.value ) #define CLOSURE_DEF operator() int main() { int i = 1,j = 2, k = 2; CLOSURE_START((i)(j)(k)) int CLOSURE_DEF (int x) const { return (i + j + k) * x; } CLOSURE_END(f0); std::cout << f0(5) << std::endl; int l = 10; CLOSURE_START((i)(j)(k)(l)) void CLOSURE_DEF(int x) { i += x; j += x; k += x; l += x; } CLOSURE_END(f1); f1(10); std::cout << i << std::endl; std::cout << j << std::endl; std::cout << k << std::endl; std::cout << l << std::endl; return 0; }
出力結果
25
11
12
12
20
多相に振舞うとか無理でした。orz
ローカルクラスにtemplateメンバー関数が持てないのでローカルクラス使ってる間は無理。
あとはきっと、どこかの変態さん成し遂げてくれるはず!