もはや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メンバー関数が持てないのでローカルクラス使ってる間は無理。
あとはきっと、どこかの変態さん成し遂げてくれるはず!

#今度はgccでも通るはず。VCはDEBGUビルドだけ通らなかった。プリプロセスかけたらちゃんと出来てたのに、謎です。