#ifndef BOOST_PP_IS_ITERATING /////////////////////////////////////////////////////////////////////////////// // Copyright 2008 Eric Niebler. Distributed under the Boost // Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // This example contains a full-featured reimplementation of the old, // now-deprecated Boost Lambda Library (BLL) on top of Boost.Proto. It // is necessarily complex to accomodate all the quirks and inconsistencies // of that old library, but it is a good example of how to build a // complete and full-featured EDLS using Proto. #ifndef BOOST_LAMBDA_HPP_EAN_04_19_2008 #define BOOST_LAMBDA_HPP_EAN_04_19_2008 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef BOOST_LAMBDA_MAX_ARITY # define BOOST_LAMBDA_MAX_ARITY 3 #endif #ifdef _MSC_VER # pragma warning(push) # pragma warning(disable: 4355) // 'this' : used in base member initializer list # pragma warning(disable: 4065) // switch statement contains 'default' but no 'case' labels #endif namespace boost { namespace lambda { namespace tag { struct if_ {}; struct if_else_ {}; struct for_ {}; struct while_ {}; struct do_while_ {}; struct protect {}; struct try_ {}; struct throw_ {}; struct rethrow_ {}; struct switch_ {}; struct default_ {}; template struct case_ { static const int value = I; }; template struct catch_ { typedef E exception_type; }; struct catch_all_ { typedef catch_all_ exception_type; }; }; template struct placeholder { typedef typename Int::tag tag; typedef typename Int::value_type value_type; typedef placeholder type; typedef placeholder next; typedef placeholder prior; static const value_type value = Int::value; friend std::ostream &operator<<(std::ostream &sout, placeholder) { return sout << "boost::lambda::_" << (Int::value+1); } }; struct exception_placeholder {}; struct no_exception_type {}; no_exception_type const no_exception = {}; // Calculate the arity of a lambda expression struct Arity : proto::or_< proto::when >, mpl::next()> , proto::when, mpl::int_<0>()> , proto::otherwise(), mpl::max()> > > {}; // True when a lambda expression can be applied with no arguments and // without an active exception object struct IsNullary : proto::or_< proto::when >, mpl::false_()> , proto::when, mpl::false_()> , proto::when, mpl::true_()> , proto::otherwise()> > > {}; struct Eval; template typename boost::result_of::type eval_lambda(Expr& e, State& s, Data& d); struct EvalWhile : proto::transform { template struct impl : proto::transform_impl { typedef mpl::void_ result_type; result_type operator()( typename impl::expr_param expr , typename impl::state_param state , typename impl::data_param data ) const { while(eval_lambda(proto::left(expr), state, data)) { eval_lambda(proto::right(expr), state, data); } return result_type(); } }; }; struct EvalDoWhile : proto::transform { template struct impl : proto::transform_impl { typedef mpl::void_ result_type; result_type operator()( typename impl::expr_param expr , typename impl::state_param state , typename impl::data_param data ) const { do { eval_lambda(proto::child_c<0>(expr), state, data); } while(eval_lambda(proto::child_c<1>(expr), state, data)); return result_type(); } }; }; struct EvalFor : proto::transform { template struct impl : proto::transform_impl { typedef mpl::void_ result_type; result_type operator()( typename impl::expr_param expr , typename impl::state_param state , typename impl::data_param data ) const { for(eval_lambda(proto::child_c<0>(expr), state, data) ; eval_lambda(proto::child_c<1>(expr), state, data) ; eval_lambda(proto::child_c<2>(expr), state, data)) { eval_lambda(proto::child_c<3>(expr), state, data); } return result_type(); } }; }; struct EvalIf : proto::transform { template struct impl : proto::transform_impl { typedef mpl::void_ result_type; result_type operator()( typename impl::expr_param expr , typename impl::state_param state , typename impl::data_param data ) const { if(eval_lambda(proto::left(expr), state, data)) { eval_lambda(proto::right(expr), state, data); } return result_type(); } }; }; struct EvalIfElse : proto::transform { template struct impl : proto::transform_impl { typedef mpl::void_ result_type; result_type operator()( typename impl::expr_param expr , typename impl::state_param state , typename impl::data_param data ) const { if(eval_lambda(proto::child_c<0>(expr), state, data)) { eval_lambda(proto::child_c<1>(expr), state, data); } else { eval_lambda(proto::child_c<2>(expr), state, data); } return result_type(); } }; }; struct EvalException : proto::transform { template struct impl : proto::transform_impl { typedef typename remove_const::type result_type; BOOST_MPL_ASSERT_NOT((is_same)); BOOST_MPL_ASSERT_NOT((is_same)); typename impl::state_param operator()( typename impl::expr_param , typename impl::state_param state , typename impl::data_param ) const { return state; } }; }; struct EvalSwitch : proto::transform { template struct impl2; #define M0(Z, N, DATA) \ case proto::tag_of::type>::type::value: \ eval_lambda(proto::child_c(expr), state, data); \ break; \ /**/ #define M1(Z, N, DATA) \ template \ struct impl2 \ : proto::transform_impl \ { \ typedef void result_type; \ \ void operator()( \ typename impl2::expr_param expr \ , typename impl2::state_param state \ , typename impl2::data_param data \ ) const \ { \ switch(eval_lambda(proto::child_c<0>(expr), state, data)) \ { \ BOOST_PP_REPEAT_FROM_TO_ ## Z(1, N, M0, ~) \ default: \ break; \ } \ } \ }; \ \ template \ struct impl2 \ : proto::transform_impl \ { \ typedef void result_type; \ \ void operator()( \ typename impl2::expr_param expr \ , typename impl2::state_param state \ , typename impl2::data_param data \ ) const \ { \ switch(eval_lambda(proto::child_c<0>(expr), state, data)) \ { \ BOOST_PP_REPEAT_FROM_TO_ ## Z(1, BOOST_PP_DEC(N), M0, ~) \ default:; \ eval_lambda(proto::child_c(expr), state, data); \ break; \ } \ } \ }; \ /**/ BOOST_PP_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1, ~) #undef M0 #undef M1 template struct impl : impl2< Expr , State , Data , proto::arity_of::value , typename proto::tag_of< typename proto::result_of::child_c< Expr , proto::arity_of::value-1 >::type >::type > {}; }; struct throw_fun { BOOST_PROTO_CALLABLE() typedef void result_type; template void operator()(Expr const &e) const { throw e; } }; struct unwrap_ref : proto::callable { template struct result; template struct result)> { typedef T &type; }; template struct result : result {}; template T &operator()(reference_wrapper const &ref) const { return ref; } }; struct anytype { template anytype(T &) { BOOST_ASSERT(false); } template operator T &() const { BOOST_ASSERT(false); throw; } private: anytype(); }; struct rethrow_fun { BOOST_PROTO_CALLABLE() typedef anytype result_type; template anytype operator()(State const &) const { BOOST_MPL_ASSERT_NOT((is_same)); throw; } }; struct Cases { template struct case_ : proto::otherwise > {}; template struct case_ > : proto::otherwise {}; template struct case_ > : proto::otherwise {}; }; template<> struct Cases::case_ : proto::otherwise {}; template<> struct Cases::case_ : proto::otherwise {}; template<> struct Cases::case_ : proto::otherwise {}; template<> struct Cases::case_ : proto::otherwise {}; template<> struct Cases::case_ : proto::otherwise {}; template<> struct Cases::case_ : proto::otherwise {}; template<> struct Cases::case_ : proto::otherwise {}; template<> struct Cases::case_ : proto::otherwise {}; template<> struct Cases::case_ : proto::otherwise {}; template<> struct Cases::case_ : proto::or_< proto::when< proto::terminal > , proto::functional::at(proto::_data, proto::_value) > , proto::when< proto::terminal , EvalException > , proto::when< proto::terminal > , unwrap_ref(proto::_value) > , proto::otherwise > > {}; template<> struct Cases::case_ : proto::or_< proto::when< proto::function > , rethrow_fun(proto::_state) > , proto::otherwise > > {}; struct Eval : proto::switch_ {}; template typename boost::result_of::type eval_lambda(Expr& e, State& s, Data& d) { return Eval()(e, s, d); } // Use a grammar to disable Proto's assignment operator overloads. // We'll define our own because we want (x+=_1) to store x by // reference. (In all other cases, variables are stored by value // within lambda expressions.) struct Grammar : proto::switch_ {}; struct AssignOps { template struct case_ : proto::_ {}; }; template<> struct AssignOps::case_ : proto::not_ {}; template<> struct AssignOps::case_ : proto::not_ {}; template<> struct AssignOps::case_ : proto::not_ {}; template<> struct AssignOps::case_ : proto::not_ {}; template<> struct AssignOps::case_ : proto::not_ {}; template<> struct AssignOps::case_ : proto::not_ {}; template<> struct AssignOps::case_ : proto::not_ {}; template<> struct AssignOps::case_ : proto::not_ {}; template<> struct AssignOps::case_ : proto::not_ {}; template<> struct AssignOps::case_ : proto::not_ {}; template struct llexpr; // Wrap expressions in lambda::llexpr<>. struct Generator : proto::pod_generator {}; // The domain for the lambda library. struct lldomain : proto::domain { // Make all terminals and children held by value instead of by reference. // Proto::domain<>::as_expr<> holds everything it can by value; the only // exceptions are function types, abstract types, and iostreams. template struct as_child : proto_base_domain::as_expr {}; // The exception is arrays, which should still be held by reference template struct as_child : proto_base_domain::as_child {}; }; template struct llresult; template struct llresult : mpl::if_c< result_of::type::value , result_of &)> , mpl::identity >::type {}; #define M0(Z, N, DATA) \ template \ struct llresult \ : result_of< \ Eval( \ This & \ , no_exception_type const & \ , BOOST_PP_CAT(fusion::vector, N) & \ ) \ > \ {}; \ /**/ BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_LAMBDA_MAX_ARITY), M0, ~) #undef M0 template struct llexpr { BOOST_PROTO_BASIC_EXTENDS(Expr, llexpr, lldomain) BOOST_PROTO_EXTENDS_ASSIGN() BOOST_PROTO_EXTENDS_SUBSCRIPT() template struct result : llresult {}; typename result::type operator()() const { fusion::vector0<> args; return eval_lambda(*this, no_exception, args); } #define M1(Z, N, _) ((0)(1)) #define M2(R, PRODUCT) M3(R, BOOST_PP_SEQ_SIZE(PRODUCT), PRODUCT) #define M3(R, SIZE, PRODUCT) \ template \ typename result::type \ operator ()(BOOST_PP_SEQ_FOR_EACH_I_R(R, M4, ~, PRODUCT)) const \ { \ BOOST_MPL_ASSERT_RELATION(result_of::type::value, <=, SIZE); \ BOOST_PP_CAT(fusion::vector, SIZE) args \ (BOOST_PP_SEQ_FOR_EACH_I_R(R, M6, ~, PRODUCT)); \ return eval_lambda(*this, no_exception, args); \ } \ /**/ #define M4(R, _, I, ELEM) \ BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM) &BOOST_PP_CAT(a, I) \ /**/ #define M5(R, _, I, ELEM) \ BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM)& \ /**/ #define M6(R, _, I, ELEM) \ BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(a, I) \ /**/ #define C0 #define C1 const #define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_LAMBDA_MAX_ARITY, "lambda.hpp")) #include BOOST_PP_ITERATE() #undef C0 #undef C1 #undef M1 #undef M2 #undef M3 #undef M4 #undef M5 #undef M6 }; typedef llexpr > >::type> placeholder1_type; typedef llexpr > >::type> placeholder2_type; typedef llexpr > >::type> placeholder3_type; placeholder1_type const _1 = {{{}}}; placeholder2_type const _2 = {{{}}}; placeholder3_type const _3 = {{{}}}; placeholder1_type const free1 = {{{}}}; placeholder2_type const free2 = {{{}}}; placeholder3_type const free3 = {{{}}}; typedef llexpr::type> placeholderE_type; placeholderE_type const _e = {{{}}}; struct byref { template struct result; template struct result { typedef llexpr::type> type; }; template struct result &)> { typedef boost::reference_wrapper > type; }; template struct result const &)> { typedef boost::reference_wrapper const> type; }; template typename result::type operator()(T &t) const { typename result::type that = {{t}}; return that; } template typename result::type operator()(T const &t) const { typename result::type that = {{t}}; return that; } template boost::reference_wrapper > operator()(llexpr &t) const { return boost::ref(t); } template boost::reference_wrapper const> operator()(llexpr const &t) const { return boost::ref(t); } }; namespace exprns_ { // Ugh, the assign operators (and only the assign operators) store // their left terminals by reference. That requires this special handling. #define BOOST_LAMBDA_DEFINE_ASSIGN_OP(OP, TAG) \ template \ typename proto::result_of::make_expr< \ TAG \ , lldomain \ , typename boost::result_of::type \ , U & \ >::type const \ operator OP(T &t, U &u) \ { \ return proto::make_expr(byref()(t), boost::ref(u)); \ } \ template \ typename proto::result_of::make_expr< \ TAG \ , lldomain \ , typename boost::result_of::type \ , U const & \ >::type const \ operator OP(T &t, U const &u) \ { \ return proto::make_expr(byref()(t), boost::ref(u)); \ } \ /**/ BOOST_LAMBDA_DEFINE_ASSIGN_OP(<<=, boost::proto::tag::shift_left_assign) BOOST_LAMBDA_DEFINE_ASSIGN_OP(>>=, boost::proto::tag::shift_right_assign) BOOST_LAMBDA_DEFINE_ASSIGN_OP(*= , boost::proto::tag::multiplies_assign) BOOST_LAMBDA_DEFINE_ASSIGN_OP(/= , boost::proto::tag::divides_assign) BOOST_LAMBDA_DEFINE_ASSIGN_OP(%= , boost::proto::tag::modulus_assign) BOOST_LAMBDA_DEFINE_ASSIGN_OP(+= , boost::proto::tag::plus_assign) BOOST_LAMBDA_DEFINE_ASSIGN_OP(-= , boost::proto::tag::minus_assign) BOOST_LAMBDA_DEFINE_ASSIGN_OP(&= , boost::proto::tag::bitwise_and_assign) BOOST_LAMBDA_DEFINE_ASSIGN_OP(|= , boost::proto::tag::bitwise_or_assign) BOOST_LAMBDA_DEFINE_ASSIGN_OP(^= , boost::proto::tag::bitwise_xor_assign) } template struct var_type { typedef llexpr::type> type; }; template llexpr::type> const var(T &t) { llexpr::type> that = {{t}}; return that; } template struct constant_type : proto::result_of::make_expr< proto::tag::terminal , lldomain , T const & > {}; template typename constant_type::type const constant(T const &t) { typename constant_type::type that = {{t}}; return that; } template struct constant_ref_type { typedef llexpr::type> type; }; template llexpr::type> const constant_ref(T const &t) { llexpr::type> that = {{t}}; return that; } template struct while_generator { explicit while_generator(Cond const &c) : cond(c) {} template typename proto::result_of::make_expr< tag::while_ , lldomain , Cond const & , Body const & >::type const operator[](Body const &body) const { return proto::make_expr( boost::ref(this->cond) , boost::ref(body) ); } private: Cond const &cond; }; template while_generator while_(Expr const &expr) { return while_generator(expr); } template struct else_generator { typedef typename proto::result_of::left::type condition_type; typedef typename proto::result_of::right::type body1_type; explicit else_generator(Expr const &expr) : if_(expr) {} template typename proto::result_of::make_expr< tag::if_else_ , lldomain , condition_type , body1_type , Body2 const & >::type const operator[](Body2 const &body2) const { return proto::make_expr( boost::ref(proto::left(this->if_)) , boost::ref(proto::right(this->if_)) , boost::ref(body2) ); } private: Expr const &if_; }; template struct with_else : Expr { template with_else(T const &expr) : Expr(expr) , else_(*this) {} else_generator else_; }; template struct if_generator { explicit if_generator(Cond const &c) : cond(c) {} template with_else< typename proto::result_of::make_expr< tag::if_ , lldomain , Cond const & , Body const & >::type > const operator[](Body const &body) const { return proto::make_expr( boost::ref(this->cond) , boost::ref(body) ); } private: Cond const &cond; }; template if_generator if_(Expr const &expr) { return if_generator(expr); } template struct for_generator { explicit for_generator(Init const &i, Cond const &c, Oper const &o) : init(i) , cond(c) , oper(o) {} template typename proto::result_of::make_expr< tag::for_ , lldomain , Init const & , Cond const & , Oper const & , Body const & >::type const operator[](Body const &body) const { return proto::make_expr( boost::ref(this->init) , boost::ref(this->cond) , boost::ref(this->oper) , boost::ref(body) ); } private: Init const &init; Cond const &cond; Oper const &oper; }; template for_generator for_(Init const &i, Cond const &c, Oper const &o) { return for_generator(i, c, o); } template struct do_while_generator { explicit do_while_generator(Body const &b) : body(b) {} template typename proto::result_of::make_expr< tag::do_while_ , lldomain , Body const & , Cond const & >::type const operator()(Cond const &cond) const { return proto::make_expr( boost::ref(this->body) , boost::ref(cond) ); } private: Body const &body; }; template struct do_body { explicit do_body(Body const &body) : while_(body) {} do_while_generator while_; }; struct do_generator { template do_body operator[](Body const &body) const { return do_body(body); } }; do_generator const do_ = {}; struct noop_fun { typedef void result_type; void operator()() const {} }; typedef llexpr::type> >::type> noop_type; noop_type const noop = {{{{{}}}}}; template typename proto::result_of::make_expr< tag::for_ , lldomain , Init const & , Cond const & , Oper const & , noop_type const & >::type const for_loop(Init const &init, Cond const &cond, Oper const &oper) { return proto::make_expr( boost::ref(init) , boost::ref(cond) , boost::ref(oper) , boost::ref(noop) ); } template typename proto::result_of::make_expr< tag::for_ , lldomain , Init const & , Cond const & , Oper const & , Body const & >::type const for_loop(Init const &init, Cond const &cond, Oper const &oper, Body const &body) { return proto::make_expr( boost::ref(init) , boost::ref(cond) , boost::ref(oper) , boost::ref(body) ); } template typename proto::result_of::make_expr< tag::while_ , lldomain , Cond const & , Body const & >::type const while_loop(Cond const &cond, Body const &body) { return proto::make_expr( boost::ref(cond) , boost::ref(body) ); } template typename proto::result_of::make_expr< tag::while_ , lldomain , Cond const & , noop_type const & >::type const while_loop(Cond const &cond) { return proto::make_expr( boost::ref(cond) , boost::ref(noop) ); } template typename proto::result_of::make_expr< tag::do_while_ , lldomain , Body const & , Cond const & >::type const do_while_loop(Cond const &cond, Body const &body) { return proto::make_expr( boost::ref(body) , boost::ref(cond) ); } template typename proto::result_of::make_expr< tag::do_while_ , lldomain , noop_type const & , Cond const & >::type const do_while_loop(Cond const &cond) { return proto::make_expr( boost::ref(noop) , boost::ref(cond) ); } template typename proto::result_of::make_expr< tag::if_ , lldomain , Cond const & , Body1 const & >::type const if_then(Cond const &cond, Body1 const &body1) { return proto::make_expr( boost::ref(cond) , boost::ref(body1) ); } template typename proto::result_of::make_expr< tag::if_else_ , lldomain , Cond const & , Body1 const & , Body2 const & >::type const if_then_else(Cond const &cond, Body1 const &body1, Body2 const &body2) { return proto::make_expr( boost::ref(cond) , boost::ref(body1) , boost::ref(body2) ); } template typename proto::result_of::make_expr< proto::tag::if_else_ , lldomain , Cond const & , Body1 const & , Body2 const & >::type const if_then_else_return(Cond const &cond, Body1 const &body1, Body2 const &body2) { return proto::make_expr( boost::ref(cond) , boost::ref(body1) , boost::ref(body2) ); } template T const &make_const(T const &t) { return t; } #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \ template \ typename proto::result_of::make_expr< \ proto::tag::function \ , lldomain \ , A_const_ref(N) \ >::type const \ bind(A_const_ref_a(N)) \ { \ return proto::make_expr(ref_a(N)); \ } \ \ template \ typename proto::result_of::make_expr< \ proto::tag::function \ , lldomain \ , A_const_ref(N) \ >::type const \ bind(A_const_ref_a(N)) \ { \ return proto::make_expr(ref_a(N)); \ } \ /**/ BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1) #undef M1 template Expr const &ret(Expr const &expr) { return expr; } template Expr const &const_parameters(Expr const &expr) { return expr; } template Expr const &break_const(Expr const &expr) { return expr; } template proto::unexpr const unlambda(Lambda const &lambda) { return proto::unexpr(lambda); } template typename proto::result_of::make_expr< tag::protect , lldomain , Lambda const & >::type const protect(Lambda const &lambda) { return proto::make_expr(boost::ref(lambda)); } template T const std_functor(T const &t) { return t; } template struct ll_static_cast_fun { typedef T result_type; template T operator()(U &u) const { return static_cast(u); } template T operator()(U const &u) const { return static_cast(u); } }; template typename proto::result_of::make_expr< proto::tag::function , lldomain , ll_static_cast_fun , U const & >::type ll_static_cast(U const &u) { ll_static_cast_fun fun; return proto::make_expr(fun, boost::ref(u)); } template struct ll_const_cast_fun { typedef T result_type; template T operator()(U &u) const { return const_cast(u); } template T operator()(U const &u) const { return const_cast(u); } }; template typename proto::result_of::make_expr< proto::tag::function , lldomain , ll_const_cast_fun , U const & >::type ll_const_cast(U const &u) { ll_const_cast_fun fun; return proto::make_expr(fun, boost::ref(u)); } template struct ll_dynamic_cast_fun { typedef T result_type; template T operator()(U &u) const { return dynamic_cast(u); } template T operator()(U const &u) const { return dynamic_cast(u); } }; template typename proto::result_of::make_expr< proto::tag::function , lldomain , ll_dynamic_cast_fun , U const & >::type ll_dynamic_cast(U const &u) { ll_dynamic_cast_fun fun; return proto::make_expr(fun, boost::ref(u)); } template struct ll_reinterpret_cast_fun { typedef T result_type; template T operator()(U &u) const { return reinterpret_cast(u); } template T operator()(U const &u) const { return reinterpret_cast(u); } }; template typename proto::result_of::make_expr< proto::tag::function , lldomain , ll_reinterpret_cast_fun , U const & >::type ll_reinterpret_cast(U const &u) { ll_reinterpret_cast_fun fun; return proto::make_expr(fun, boost::ref(u)); } struct ll_sizeof_fun { typedef std::size_t result_type; template std::size_t operator()(U const &) const { return sizeof(U); } }; template typename proto::result_of::make_expr< proto::tag::function , lldomain , ll_sizeof_fun , U const & >::type ll_sizeof(U const &u) { ll_sizeof_fun fun; return proto::make_expr(fun, boost::ref(u)); } struct ll_typeid_fun { typedef std::type_info const &result_type; template std::type_info const &operator()(U const &) const { return typeid(U); } }; template typename proto::result_of::make_expr< proto::tag::function , lldomain , ll_typeid_fun , U const & >::type ll_typeid(U const &u) { ll_typeid_fun fun; return proto::make_expr(fun, boost::ref(u)); } template struct constructor { typedef T result_type; T operator()() const { return T(); } #define M0(Z, N, DATA) \ template \ T operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const \ { \ return T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \ } \ /**/ BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~) #undef M0 }; template struct new_ptr { typedef T *result_type; T *operator()() const { return new T(); } #define M0(Z, N, DATA) \ template \ T *operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const \ { \ return new T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \ } \ /**/ BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~) #undef M0 }; struct destructor { typedef void result_type; template void operator()(T const &t) const { t.~T(); } template void operator()(T *const &t) const { (*t).~T(); } }; struct delete_ptr { typedef void result_type; template void operator()(T *t) const { delete t; } }; template struct new_array { typedef T *result_type; T *operator()(std::size_t n) const { return new T[n]; } }; struct delete_array { typedef void result_type; template void operator()(T *t) const { delete[] t; } }; template struct type2type {}; struct try_catch_nil {}; template struct try_catch_cons : Tail { typedef typename Head::proto_tag::exception_type exception_type; try_catch_cons(Head const &head, Tail const &tail) : Tail(tail) , head(head) {} template typename result_of::type operator()(State const &state, Data &data) const { return this->invoke(state, data, type2type()); } private: // catch(Exception const &) template typename result_of::type invoke(State const &state, Data &data, type2type) const { typedef typename result_of::type result_type; try { return static_cast(this->Tail::operator()(state, data)); } catch(Exception const &e) { return static_cast(eval_lambda(this->head, e, data)); } } // catch(...) template typename result_of::type invoke(State const &state, Data &data, type2type) const { typedef typename result_of::type result_type; try { return static_cast(this->Tail::operator()(state, data)); } catch(...) { return static_cast(eval_lambda(this->head, tag::catch_all_(), data)); } } Head const &head; }; template struct try_catch_cons : proto::callable { try_catch_cons(Head const &head, try_catch_nil const &) : head(head) {} template struct result; template struct result : result_of {}; template typename result_of::type operator()(State const &state, Data &data) const { return eval_lambda(this->head, state, data); } private: Head const &head; }; struct try_catch_fun : proto::callable { template struct result; template struct result : result_of {}; template typename result_of::type operator()(Fun const &fun, State const &state, Data &data) const { return fun(state, data); } }; template<> struct Cases::case_ : proto::otherwise< try_catch_fun( proto::fold< proto::_ , try_catch_nil() , try_catch_cons(proto::_, proto::_state) > , proto::_state , proto::_data ) > {}; template typename proto::result_of::make_expr, lldomain, Expr const &>::type const catch_exception(Expr const &expr) { return proto::make_expr, lldomain>(boost::ref(expr)); } template typename proto::result_of::make_expr, lldomain, noop_type const &>::type const catch_exception() { return proto::make_expr, lldomain>(boost::ref(noop)); } template typename proto::result_of::make_expr< tag::catch_all_ , lldomain , Expr const & >::type const catch_all(Expr const &expr) { return proto::make_expr(boost::ref(expr)); } inline proto::result_of::make_expr::type const catch_all() { return proto::make_expr(boost::ref(noop)); } #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \ template \ typename proto::result_of::make_expr< \ tag::try_ \ , lldomain \ , A_const_ref(N) \ >::type const \ try_catch(A_const_ref_a(N)) \ { \ return proto::make_expr(ref_a(N)); \ } \ /**/ BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1) #undef M1 template typename proto::result_of::make_expr< proto::tag::function , lldomain , throw_fun , Expr const & >::type const throw_exception(Expr const &expr) { throw_fun fun; return proto::make_expr(fun, boost::ref(expr)); } inline proto::result_of::make_expr::type const rethrow() { return proto::make_expr(rethrow_fun()); } struct make_void_fun { typedef void result_type; template void operator()(T const &) const {} }; template typename proto::result_of::make_expr< proto::tag::function , lldomain , make_void_fun , Expr const & >::type const make_void(Expr const &expr) { make_void_fun fun; return proto::make_expr(fun, boost::ref(expr)); } #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \ template \ typename proto::result_of::make_expr< \ tag::switch_ \ , lldomain \ , A_const_ref(N) \ >::type const \ switch_statement(A_const_ref_a(N)) \ { \ return proto::make_expr(ref_a(N)); \ } \ /**/ BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1) #undef M1 template typename proto::result_of::make_expr, lldomain, Expr const &>::type const case_statement(Expr const &expr) { return proto::make_expr, lldomain>(boost::ref(expr)); } template typename proto::result_of::make_expr, lldomain, noop_type const &>::type const case_statement() { return proto::make_expr, lldomain>(boost::ref(noop)); } template typename proto::result_of::make_expr::type const default_statement(Expr const &expr) { return proto::make_expr(boost::ref(expr)); } inline proto::result_of::make_expr::type const default_statement() { return proto::make_expr(boost::ref(noop)); } namespace ll { struct for_each { template struct result; template struct result : remove_const::type> {}; template Fun operator()(InIter begin, InIter end, Fun fun) const { return std::for_each(begin, end, fun); } }; } }} namespace boost { template struct result_of()> : lambda::llexpr::template result()> {}; template struct result_of const()> : lambda::llexpr::template result const()> {}; } #ifdef _MSC_VER # pragma warning(pop) #endif #endif #else BOOST_PP_SEQ_FOR_EACH_PRODUCT( M2, BOOST_PP_REPEAT(BOOST_PP_ITERATION(), M1, ~) ) #endif