#ifndef BOOST_PP_IS_ITERATING #ifndef BOOST_LAMBDA_HPP_EAN_04_19_2008 #define BOOST_LAMBDA_HPP_EAN_04_19_2008 #define BOOST_MPL_LIMIT_METAFUNCTION_ARITY 10 #define BOOST_PROTO_MAX_ARITY 10 #define BOOST_PROTO_MAX_FUNCTION_CALL_ARITY 5 #include <iosfwd> #include <typeinfo> #include <algorithm> #include <boost/ref.hpp> #include <boost/assert.hpp> #include <boost/mpl/or.hpp> #include <boost/mpl/int.hpp> #include <boost/mpl/void.hpp> #include <boost/mpl/identity.hpp> #include <boost/mpl/next_prior.hpp> #include <boost/mpl/min_max.hpp> #include <boost/mpl/assert.hpp> #include <boost/mpl/apply_wrap.hpp> #include <boost/preprocessor.hpp> #include <boost/utility/enable_if.hpp> #include <boost/utility/result_of.hpp> #include <boost/fusion/include/vector.hpp> #include <boost/type_traits/add_reference.hpp> #include <boost/type_traits/remove_reference.hpp> #include <boost/type_traits/remove_const.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_abstract.hpp> #include <boost/type_traits/is_array.hpp> #include <boost/type_traits/is_function.hpp> #include <boost/proto/proto.hpp> #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<int I> struct case_ { BOOST_STATIC_CONSTANT(int, value = I); }; template<typename E> struct catch_ { typedef E exception_type; }; struct catch_all_ { typedef catch_all_ exception_type; }; }; template<typename Int> struct placeholder { typedef typename Int::tag tag; typedef typename Int::value_type value_type; typedef placeholder<Int> type; typedef placeholder<typename Int::next> next; typedef placeholder<typename Int::prior> prior; BOOST_STATIC_CONSTANT(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<proto::terminal<placeholder<proto::_> >, mpl::next<proto::_value>()> , proto::when<proto::terminal<proto::_>, mpl::int_<0>()> , proto::otherwise<proto::fold<proto::_, mpl::int_<0>(), mpl::max<proto::_state, Arity>()> > > {}; // True when a lambda expression can be applied with no arguments and // without an active exception object struct IsNullary : proto::or_< proto::when<proto::terminal<placeholder<proto::_> >, mpl::false_()> , proto::when<proto::terminal<exception_placeholder>, mpl::false_()> , proto::when<proto::terminal<proto::_>, mpl::true_()> , proto::otherwise<proto::fold<proto::_, mpl::true_(), mpl::and_<proto::_state, IsNullary>()> > > {}; struct at : proto::callable { template<class Sig> struct result; template<class This, class Cont, class Int> struct result<This(Cont, Int)> : fusion::result_of::at< typename remove_reference<Cont>::type , typename remove_reference<Int>::type > {}; template<typename Cont, typename Int> typename fusion::result_of::at<Cont, Int>::type operator ()(Cont &cont, Int const &) const { return fusion::at<Int>(cont); } }; struct Eval; struct EvalWhile : proto::transform<EvalWhile> { template<typename Expr, typename State, typename Data> struct impl : proto::transform_impl<Expr, State, Data> { 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()(proto::left(expr), state, data)) { Eval()(proto::right(expr), state, data); } return result_type(); } }; }; struct EvalDoWhile : proto::transform<EvalDoWhile> { template<typename Expr, typename State, typename Data> struct impl : proto::transform_impl<Expr, State, Data> { 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()(proto::child_c<0>(expr), state, data); } while(Eval()(proto::child_c<1>(expr), state, data)); return result_type(); } }; }; struct EvalFor : proto::transform<EvalFor> { template<typename Expr, typename State, typename Data> struct impl : proto::transform_impl<Expr, State, Data> { 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()(proto::child_c<0>(expr), state, data) ; Eval()(proto::child_c<1>(expr), state, data) ; Eval()(proto::child_c<2>(expr), state, data)) { Eval()(proto::child_c<3>(expr), state, data); } return result_type(); } }; }; struct EvalIf : proto::transform<EvalIf> { template<typename Expr, typename State, typename Data> struct impl : proto::transform_impl<Expr, State, Data> { 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()(proto::left(expr), state, data)) { Eval()(proto::right(expr), state, data); } return result_type(); } }; }; struct EvalIfElse : proto::transform<EvalIfElse> { template<typename Expr, typename State, typename Data> struct impl : proto::transform_impl<Expr, State, Data> { 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()(proto::child_c<0>(expr), state, data)) { Eval()(proto::child_c<1>(expr), state, data); } else { Eval()(proto::child_c<2>(expr), state, data); } return result_type(); } }; }; struct EvalException : proto::transform<EvalException> { template<typename Expr, typename State, typename Data> struct impl : proto::transform_impl<Expr, State, Data> { typedef typename remove_const<typename impl::state>::type result_type; BOOST_MPL_ASSERT_NOT((is_same<result_type, no_exception_type>)); BOOST_MPL_ASSERT_NOT((is_same<result_type, tag::catch_all_>)); 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<EvalSwitch> { template<typename Expr, typename State, typename Data, long Arity, typename BackTag> struct impl2; #define M0(Z, N, DATA) \ case proto::tag_of<typename proto::result_of::child_c<Expr, N>::type>::type::value: \ Eval()(proto::child_c<N>(expr), state, data); \ break; \ /**/ #define M1(Z, N, DATA) \ template<typename Expr, typename State, typename Data, typename BackTag> \ struct impl2<Expr, State, Data, N, BackTag> \ : proto::transform_impl<Expr, State, Data> \ { \ typedef void result_type; \ \ void operator()( \ typename impl2::expr_param expr \ , typename impl2::state_param state \ , typename impl2::data_param data \ ) const \ { \ switch(Eval()(proto::child_c<0>(expr), state, data)) \ { \ BOOST_PP_REPEAT_FROM_TO_ ## Z(1, N, M0, ~) \ default: \ break; \ } \ } \ }; \ \ template<typename Expr, typename State, typename Data> \ struct impl2<Expr, State, Data, N, tag::default_> \ : proto::transform_impl<Expr, State, Data> \ { \ typedef void result_type; \ \ void operator()( \ typename impl2::expr_param expr \ , typename impl2::state_param state \ , typename impl2::data_param data \ ) const \ { \ switch(Eval()(proto::child_c<0>(expr), state, data)) \ { \ BOOST_PP_REPEAT_FROM_TO_ ## Z(1, BOOST_PP_DEC(N), M0, ~) \ default:; \ Eval()(proto::child_c<BOOST_PP_DEC(N)>(expr), state, data); \ break; \ } \ } \ }; \ /**/ BOOST_PP_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1, ~) #undef M0 #undef M1 template<typename Expr, typename State, typename Data> struct impl : impl2< Expr , State , Data , proto::arity_of<Expr>::value , typename proto::tag_of< typename proto::result_of::child_c< Expr , proto::arity_of<Expr>::value-1 >::type >::type > {}; }; struct throw_fun { BOOST_PROTO_CALLABLE() typedef void result_type; template<typename Expr> void operator()(Expr const &e) const { throw e; } }; struct unwrap_ref : proto::callable { template<typename Sig> struct result; template<typename This, typename T> struct result<This(reference_wrapper<T>)> { typedef T &type; }; template<typename This, typename T> struct result<This(T &)> : result<This(T)> {}; template<typename T> T &operator()(reference_wrapper<T> const &ref) const { return ref; } }; struct anytype { template<typename T> anytype(T &) { BOOST_ASSERT(false); } template<typename T> operator T &() const { BOOST_ASSERT(false); throw; } private: anytype(); }; struct rethrow_fun { BOOST_PROTO_CALLABLE() typedef anytype result_type; template<typename State> anytype operator()(State const &) const { BOOST_MPL_ASSERT_NOT((is_same<State, no_exception_type>)); throw; } }; struct Cases { template<typename Tag> struct case_ : proto::otherwise<proto::_default<Eval> > {}; template<typename E> struct case_<tag::catch_<E> > : proto::otherwise<Eval(proto::_child)> {}; template<int I> struct case_<tag::case_<I> > : proto::otherwise<Eval(proto::_child)> {}; }; template<> struct Cases::case_<tag::while_> : proto::otherwise<EvalWhile> {}; template<> struct Cases::case_<tag::for_> : proto::otherwise<EvalFor> {}; template<> struct Cases::case_<tag::if_> : proto::otherwise<EvalIf> {}; template<> struct Cases::case_<tag::if_else_> : proto::otherwise<EvalIfElse> {}; template<> struct Cases::case_<tag::do_while_> : proto::otherwise<EvalDoWhile> {}; template<> struct Cases::case_<tag::switch_> : proto::otherwise<EvalSwitch> {}; template<> struct Cases::case_<tag::protect> : proto::otherwise<proto::_child> {}; template<> struct Cases::case_<tag::default_> : proto::otherwise<Eval(proto::_child)> {}; template<> struct Cases::case_<tag::catch_all_> : proto::otherwise<Eval(proto::_child)> {}; template<> struct Cases::case_<proto::tag::terminal> : proto::or_< proto::when< proto::terminal<placeholder<proto::_> > , at(proto::_data, proto::_value) > , proto::when< proto::terminal<exception_placeholder> , EvalException > , proto::when< proto::terminal<reference_wrapper<proto::_> > , unwrap_ref(proto::_value) > , proto::otherwise<proto::_default<Eval> > > {}; template<> struct Cases::case_<proto::tag::function> : proto::or_< proto::when< proto::function<proto::terminal<rethrow_fun> > , rethrow_fun(proto::_state) > , proto::otherwise<proto::_default<Eval> > > {}; struct Eval : proto::switch_<Cases> {}; // 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> {}; struct AssignOps { template<typename Tag> struct case_ : proto::_ {}; }; template<> struct AssignOps::case_<proto::tag::shift_left_assign> : proto::not_<proto::_> {}; template<> struct AssignOps::case_<proto::tag::shift_right_assign> : proto::not_<proto::_> {}; template<> struct AssignOps::case_<proto::tag::multiplies_assign> : proto::not_<proto::_> {}; template<> struct AssignOps::case_<proto::tag::divides_assign> : proto::not_<proto::_> {}; template<> struct AssignOps::case_<proto::tag::modulus_assign> : proto::not_<proto::_> {}; template<> struct AssignOps::case_<proto::tag::plus_assign> : proto::not_<proto::_> {}; template<> struct AssignOps::case_<proto::tag::minus_assign> : proto::not_<proto::_> {}; template<> struct AssignOps::case_<proto::tag::bitwise_and_assign> : proto::not_<proto::_> {}; template<> struct AssignOps::case_<proto::tag::bitwise_or_assign> : proto::not_<proto::_> {}; template<> struct AssignOps::case_<proto::tag::bitwise_xor_assign> : proto::not_<proto::_> {}; namespace exprns_ { template<typename Expr> struct llexpr; } using exprns_::llexpr; template<typename T> struct is_stream { private: static T &t; typedef char yes_type; typedef char (&no_type)[2]; static no_type test_is_stream(...); template<typename Char, typename Traits> static yes_type test_is_stream(std::basic_istream<Char, Traits> &); template<typename Char, typename Traits> static yes_type test_is_stream(std::basic_ostream<Char, Traits> &); public: typedef bool value_type; BOOST_STATIC_CONSTANT(bool, value = sizeof(yes_type) == sizeof(test_is_stream(t))); typedef mpl::bool_<value> type; }; // These terminal types are always stored by reference template<typename Value> struct store_by_ref : mpl::or_< is_abstract<Value> , is_array<Value> , is_function<Value> , is_stream<Value> > {}; // Wrap expressions in lambda::llexpr<>, and hold children nodes // and some terminal types by value. struct Generator : proto::or_< proto::when< proto::and_< proto::terminal<proto::_> , proto::if_<store_by_ref<proto::_value>()> > , proto::pod_generator<llexpr>(proto::_) > , proto::otherwise< proto::compose_generators< proto::by_value_generator , proto::pod_generator<llexpr> >(proto::_) > > {}; struct lldomain : proto::domain<Generator, Grammar> {}; template<typename Sig> struct llresult; template<typename This> struct llresult<This()> : mpl::if_c< result_of<IsNullary(This &)>::type::value , result_of<Eval(This &, no_exception_type const &, fusion::vector0 &)> , mpl::identity<void> >::type {}; #define M0(Z, N, DATA) \ template<typename This BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, typename A)> \ struct llresult<This(BOOST_PP_ENUM_PARAMS_Z(Z, N, A))> \ : result_of< \ Eval( \ This & \ , no_exception_type const & \ , BOOST_PP_CAT(fusion::vector, N)<BOOST_PP_ENUM_PARAMS_Z(Z, N, A)> & \ ) \ > \ {}; \ /**/ BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_LAMBDA_MAX_ARITY), M0, ~) #undef M0 template<typename Expr> struct llexpr { BOOST_PROTO_BASIC_EXTENDS(Expr, llexpr<Expr>, lldomain) BOOST_PROTO_EXTENDS_ASSIGN() BOOST_PROTO_EXTENDS_SUBSCRIPT() template<typename Sig> struct result : llresult<Sig> {}; typename result<llexpr const()>::type operator()() const { fusion::vector0 args; return Eval()(*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<BOOST_PP_ENUM_PARAMS(SIZE, typename A)> \ typename result<llexpr const(BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT))>::type \ operator ()(BOOST_PP_SEQ_FOR_EACH_I_R(R, M4, ~, PRODUCT)) const \ { \ BOOST_MPL_ASSERT_RELATION(result_of<Arity(Expr const &)>::type::value, <=, SIZE); \ BOOST_PP_CAT(fusion::vector, SIZE)<BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT)> args \ (BOOST_PP_SEQ_FOR_EACH_I_R(R, M6, ~, PRODUCT)); \ return Eval()(*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<proto::terminal<placeholder<mpl::int_<0> > >::type> placeholder1_type; typedef llexpr<proto::terminal<placeholder<mpl::int_<1> > >::type> placeholder2_type; typedef llexpr<proto::terminal<placeholder<mpl::int_<2> > >::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<proto::terminal<exception_placeholder>::type> placeholderE_type; placeholderE_type const _e = {{{}}}; struct byref { template<typename Sig> struct result; template<typename This, typename T> struct result<This(T &)> { typedef llexpr<typename proto::terminal<T &>::type> type; }; template<typename This, typename T> struct result<This(llexpr<T> &)> { typedef boost::reference_wrapper<llexpr<T> > type; }; template<typename This, typename T> struct result<This(llexpr<T> const &)> { typedef boost::reference_wrapper<llexpr<T> const> type; }; template<typename T> typename result<byref(T &)>::type operator()(T &t) const { typename result<byref(T &)>::type that = {{t}}; return that; } template<typename T> typename result<byref(T const &)>::type operator()(T const &t) const { typename result<byref(T const &)>::type that = {{t}}; return that; } template<typename T> boost::reference_wrapper<llexpr<T> > operator()(llexpr<T> &t) const { return boost::ref(t); } template<typename T> boost::reference_wrapper<llexpr<T> const> operator()(llexpr<T> 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 T, typename U> \ typename proto::result_of::make_expr< \ TAG \ , lldomain \ , typename boost::result_of<byref(T &)>::type \ , U & \ >::type const \ operator OP(T &t, U &u) \ { \ return proto::make_expr<TAG, lldomain>(byref()(t), boost::ref(u)); \ } \ template<typename T, typename U> \ typename proto::result_of::make_expr< \ TAG \ , lldomain \ , typename boost::result_of<byref(T &)>::type \ , U const & \ >::type const \ operator OP(T &t, U const &u) \ { \ return proto::make_expr<TAG, lldomain>(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<typename T> struct var_type { typedef llexpr<typename proto::terminal<T &>::type> type; }; template<typename T> llexpr<typename proto::terminal<T &>::type> const var(T &t) { llexpr<typename proto::terminal<T &>::type> that = {{t}}; return that; } template<typename T> struct constant_type : proto::result_of::make_expr< proto::tag::terminal , lldomain , T const & > {}; template<typename T> typename constant_type<T>::type const constant(T const &t) { typename constant_type<T>::type that = {{t}}; return that; } template<typename T> struct constant_ref_type { typedef llexpr<typename proto::terminal<T const &>::type> type; }; template<typename T> llexpr<typename proto::terminal<T const &>::type> const constant_ref(T const &t) { llexpr<typename proto::terminal<T const &>::type> that = {{t}}; return that; } template<typename Cond> struct while_generator { explicit while_generator(Cond const &c) : cond(c) {} template<typename Body> typename proto::result_of::make_expr< tag::while_ , lldomain , Cond const & , Body const & >::type const operator[](Body const &body) const { return proto::make_expr<tag::while_, lldomain>( boost::ref(this->cond) , boost::ref(body) ); } private: Cond const &cond; }; template<typename Expr> while_generator<Expr> while_(Expr const &expr) { return while_generator<Expr>(expr); } template<typename Expr> struct else_generator { typedef typename proto::result_of::left<Expr const &>::type condition_type; typedef typename proto::result_of::right<Expr const &>::type body1_type; explicit else_generator(Expr const &expr) : if_(expr) {} template<typename Body2> 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<tag::if_else_, lldomain>( boost::ref(proto::left(this->if_)) , boost::ref(proto::right(this->if_)) , boost::ref(body2) ); } private: Expr const &if_; }; template<typename Expr> struct with_else : Expr { template<typename T> with_else(T const &expr) : Expr(expr) , else_(*this) {} else_generator<Expr> else_; }; template<typename Cond> struct if_generator { explicit if_generator(Cond const &c) : cond(c) {} template<typename Body> 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<tag::if_, lldomain>( boost::ref(this->cond) , boost::ref(body) ); } private: Cond const &cond; }; template<typename Expr> if_generator<Expr> if_(Expr const &expr) { return if_generator<Expr>(expr); } template<typename Init, typename Cond, typename Oper> struct for_generator { explicit for_generator(Init const &i, Cond const &c, Oper const &o) : init(i) , cond(c) , oper(o) {} template<typename Body> 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<tag::for_, lldomain>( 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<typename Init, typename Cond, typename Oper> for_generator<Init, Cond, Oper> for_(Init const &i, Cond const &c, Oper const &o) { return for_generator<Init, Cond, Oper>(i, c, o); } template<typename Body> struct do_while_generator { explicit do_while_generator(Body const &b) : body(b) {} template<typename Cond> 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<tag::do_while_, lldomain>( boost::ref(this->body) , boost::ref(cond) ); } private: Body const &body; }; template<typename Body> struct do_body { explicit do_body(Body const &body) : while_(body) {} do_while_generator<Body> while_; }; struct do_generator { template<typename Body> do_body<Body> operator[](Body const &body) const { return do_body<Body>(body); } }; do_generator const do_ = {}; struct noop_fun { typedef void result_type; void operator()() const {} }; typedef llexpr<proto::function<llexpr<proto::terminal<noop_fun>::type> >::type> noop_type; noop_type const noop = {{{{{}}}}}; template<typename Init, typename Cond, typename Oper> 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<tag::for_, lldomain>( boost::ref(init) , boost::ref(cond) , boost::ref(oper) , boost::ref(noop) ); } template<typename Init, typename Cond, typename Oper, typename Body> 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<tag::for_>( boost::ref(init) , boost::ref(cond) , boost::ref(oper) , boost::ref(body) ); } template<typename Cond, typename Body> 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<tag::while_, lldomain>( boost::ref(cond) , boost::ref(body) ); } template<typename Cond> 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<tag::while_, lldomain>( boost::ref(cond) , boost::ref(noop) ); } template<typename Cond, typename Body> 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<tag::do_while_, lldomain>( boost::ref(body) , boost::ref(cond) ); } template<typename Cond> 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<tag::do_while_, lldomain>( boost::ref(noop) , boost::ref(cond) ); } template<typename Cond, typename Body1> 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<tag::if_, lldomain>( boost::ref(cond) , boost::ref(body1) ); } template<typename Cond, typename Body1, typename Body2> 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<tag::if_else_, lldomain>( boost::ref(cond) , boost::ref(body1) , boost::ref(body2) ); } template<typename Cond, typename Body1, typename Body2> 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<proto::tag::if_else_, lldomain>( boost::ref(cond) , boost::ref(body1) , boost::ref(body2) ); } template<typename T> 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_A(N)> \ 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<proto::tag::function, lldomain>(ref_a(N)); \ } \ \ template<typename Ret, typename_A(N)> \ 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<proto::tag::function, lldomain>(ref_a(N)); \ } \ /**/ BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1) #undef M1 template<typename Ret, typename Expr> Expr const &ret(Expr const &expr) { return expr; } template<typename Expr> Expr const &const_parameters(Expr const &expr) { return expr; } template<typename Expr> Expr const &break_const(Expr const &expr) { return expr; } template<typename Lambda> proto::unexpr<Lambda> const unlambda(Lambda const &lambda) { return proto::unexpr<Lambda>(lambda); } template<typename Lambda> typename proto::result_of::make_expr< tag::protect , lldomain , Lambda const & >::type const protect(Lambda const &lambda) { return proto::make_expr<tag::protect, lldomain>(boost::ref(lambda)); } template<typename T> T const std_functor(T const &t) { return t; } template<typename T> struct ll_static_cast_fun { typedef T result_type; template<typename U> T operator()(U &u) const { return static_cast<T>(u); } template<typename U> T operator()(U const &u) const { return static_cast<T>(u); } }; template<typename T, typename U> typename proto::result_of::make_expr< proto::tag::function , lldomain , ll_static_cast_fun<T> , U const & >::type ll_static_cast(U const &u) { ll_static_cast_fun<T> fun; return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); } template<typename T> struct ll_const_cast_fun { typedef T result_type; template<typename U> T operator()(U &u) const { return const_cast<T>(u); } template<typename U> T operator()(U const &u) const { return const_cast<T>(u); } }; template<typename T, typename U> typename proto::result_of::make_expr< proto::tag::function , lldomain , ll_const_cast_fun<T> , U const & >::type ll_const_cast(U const &u) { ll_const_cast_fun<T> fun; return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); } template<typename T> struct ll_dynamic_cast_fun { typedef T result_type; template<typename U> T operator()(U &u) const { return dynamic_cast<T>(u); } template<typename U> T operator()(U const &u) const { return dynamic_cast<T>(u); } }; template<typename T, typename U> typename proto::result_of::make_expr< proto::tag::function , lldomain , ll_dynamic_cast_fun<T> , U const & >::type ll_dynamic_cast(U const &u) { ll_dynamic_cast_fun<T> fun; return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); } template<typename T> struct ll_reinterpret_cast_fun { typedef T result_type; template<typename U> T operator()(U &u) const { return reinterpret_cast<T>(u); } template<typename U> T operator()(U const &u) const { return reinterpret_cast<T>(u); } }; template<typename T, typename U> typename proto::result_of::make_expr< proto::tag::function , lldomain , ll_reinterpret_cast_fun<T> , U const & >::type ll_reinterpret_cast(U const &u) { ll_reinterpret_cast_fun<T> fun; return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u)); } struct ll_sizeof_fun { typedef std::size_t result_type; template<typename U> std::size_t operator()(U const &) const { return sizeof(U); } }; template<typename U> 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<proto::tag::function, lldomain>(fun, boost::ref(u)); } struct ll_typeid_fun { typedef std::type_info const &result_type; template<typename U> std::type_info const &operator()(U const &) const { return typeid(U); } }; template<typename U> 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<proto::tag::function, lldomain>(fun, boost::ref(u)); } template<typename T> struct constructor { typedef T result_type; T operator()() const { return T(); } #define M0(Z, N, DATA) \ template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \ 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<typename T> struct new_ptr { typedef T *result_type; T *operator()() const { return new T(); } #define M0(Z, N, DATA) \ template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \ 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<typename T> void operator()(T const &t) const { t.~T(); } template<typename T> void operator()(T *const &t) const { (*t).~T(); } }; struct delete_ptr { typedef void result_type; template<typename T> void operator()(T *t) const { delete t; } }; template<typename T> 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<typename T> void operator()(T *t) const { delete[] t; } }; template<typename T> struct type2type {}; struct try_catch_nil {}; template<typename Head, typename Tail> 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 State, typename Data> typename result_of<Tail const(State const &, Data &)>::type operator()(State const &state, Data &data) const { return this->invoke(state, data, type2type<exception_type>()); } private: // catch(Exception const &) template<typename State, typename Data, typename Exception> typename result_of<Tail const(State const &, Data &)>::type invoke(State const &state, Data &data, type2type<Exception>) const { typedef typename result_of<Tail const(State const &, Data &)>::type result_type; try { return static_cast<result_type>(this->Tail::operator()(state, data)); } catch(Exception const &e) { return static_cast<result_type>(Eval()(this->head, e, data)); } } // catch(...) template<typename State, typename Data> typename result_of<Tail const(State const &, Data &)>::type invoke(State const &state, Data &data, type2type<tag::catch_all_>) const { typedef typename result_of<Tail const(State const &, Data &)>::type result_type; try { return static_cast<result_type>(this->Tail::operator()(state, data)); } catch(...) { return static_cast<result_type>(Eval()(this->head, tag::catch_all_(), data)); } } Head const &head; }; template<typename Head> struct try_catch_cons<Head, try_catch_nil> : proto::callable { try_catch_cons(Head const &head, try_catch_nil const &) : head(head) {} template<typename Sig> struct result; template<typename This, typename State, typename Data> struct result<This(State, Data)> : result_of<Eval(Head const &, State, Data)> {}; template<typename State, typename Data> typename result_of<Eval(Head const &, State, Data)>::type operator()(State const &state, Data &data) const { return Eval()(this->head, state, data); } private: Head const &head; }; struct try_catch_fun : proto::callable { template<typename Sig> struct result; template<typename This, typename Fun, typename State, typename Data> struct result<This(Fun, State, Data)> : result_of<Fun(State, Data)> {}; template<typename Fun, typename State, typename Data> typename result_of<Fun(State const &, Data &)>::type operator()(Fun const &fun, State const &state, Data &data) const { return fun(state, data); } }; template<> struct Cases::case_<tag::try_> : proto::otherwise< try_catch_fun( proto::fold< proto::_ , try_catch_nil() , try_catch_cons<proto::_, proto::_state>(proto::_, proto::_state) > , proto::_state , proto::_data ) > {}; template<typename E, typename Expr> typename proto::result_of::make_expr<tag::catch_<E>, lldomain, Expr const &>::type const catch_exception(Expr const &expr) { return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(expr)); } template<typename E> typename proto::result_of::make_expr<tag::catch_<E>, lldomain, noop_type const &>::type const catch_exception() { return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(noop)); } template<typename Expr> typename proto::result_of::make_expr< tag::catch_all_ , lldomain , Expr const & >::type const catch_all(Expr const &expr) { return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(expr)); } inline proto::result_of::make_expr<tag::catch_all_, lldomain, noop_type const &>::type const catch_all() { return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(noop)); } #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \ template<typename_A(N)> \ 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<tag::try_, lldomain>(ref_a(N)); \ } \ /**/ BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1) #undef M1 template<typename Expr> 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<proto::tag::function, lldomain>(fun, boost::ref(expr)); } inline proto::result_of::make_expr<proto::tag::function, lldomain, rethrow_fun>::type const rethrow() { return proto::make_expr<proto::tag::function, lldomain>(rethrow_fun()); } struct make_void_fun { typedef void result_type; template<typename T> void operator()(T const &) const {} }; template<typename Expr> 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<proto::tag::function, lldomain>(fun, boost::ref(expr)); } #define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \ template<typename_A(N)> \ 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<tag::switch_, lldomain>(ref_a(N)); \ } \ /**/ BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1) #undef M1 template<int I, typename Expr> typename proto::result_of::make_expr<tag::case_<I>, lldomain, Expr const &>::type const case_statement(Expr const &expr) { return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(expr)); } template<int I> typename proto::result_of::make_expr<tag::case_<I>, lldomain, noop_type const &>::type const case_statement() { return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(noop)); } template<typename Expr> typename proto::result_of::make_expr<tag::default_, lldomain, Expr const &>::type const default_statement(Expr const &expr) { return proto::make_expr<tag::default_, lldomain>(boost::ref(expr)); } inline proto::result_of::make_expr<tag::default_, lldomain, noop_type const &>::type const default_statement() { return proto::make_expr<tag::default_, lldomain>(boost::ref(noop)); } namespace ll { struct for_each { template<typename Sig> struct result; template<typename This, typename Begin, typename End, typename Fun> struct result<This(Begin, End, Fun)> : remove_const<typename remove_reference<Fun>::type> {}; template<typename InIter, typename Fun> Fun operator()(InIter begin, InIter end, Fun fun) const { return std::for_each(begin, end, fun); } }; } }} namespace boost { template<typename Expr> struct result_of<lambda::llexpr<Expr>()> : lambda::llexpr<Expr>::template result<lambda::llexpr<Expr>()> {}; template<typename Expr> struct result_of<lambda::llexpr<Expr> const()> : lambda::llexpr<Expr>::template result<lambda::llexpr<Expr> 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