#include #include #include #include namespace boost { namespace phoenix { using namespace proto; ////////////////////////////// // phoenix expression wrapper template struct actor; ////////////////////////////// struct phoenix_domain : domain > {}; ////////////////////////////// // phoenix grammar and expression evaluator struct eval : switch_ {}; ////////////////////////////// struct eval_cases { template struct case_ : _default {}; }; ////////////////////////////// template struct actor_result; #define BOOST_PROTO_LOCAL_MACRO(N, class_A, A, A_const_ref_a, a)\ template \ struct actor_result \ : boost::result_of &)> \ {}; #define BOOST_PROTO_LOCAL_A BOOST_PROTO_A #include BOOST_PROTO_LOCAL_ITERATE() ////////////////////////////// template struct actor { #define BOOST_PHOENIX_ACTOR(Base, Derived, Domain) \ BOOST_PROTO_BASIC_EXTENDS(Base, Derived, Domain) \ BOOST_PROTO_EXTENDS_ASSIGN() \ BOOST_PROTO_EXTENDS_SUBSCRIPT() \ \ template \ struct result : actor_result \ {}; \ \ typedef Derived actor_type; \ BOOST_PROTO_REPEAT(BOOST_PHOENIX_INVOKE) \ /**/ #define BOOST_PHOENIX_INVOKE(N, class_A, A_const_ref, A_const_ref_a, a) \ template \ typename boost::result_of::type \ operator()(A_const_ref_a(N)) const \ { \ BOOST_PROTO_ASSERT_MATCHES(*this, eval); \ fusion::vector args(a(N)); \ return eval()(*this, args); \ } \ /**/ BOOST_PHOENIX_ACTOR(Expr, actor, phoenix_domain) }; ////////////////////////////// // Begin implementation of _1, _2, _3 argument placeholders // struct arg_tag {}; ////////////////////////////// struct at : callable { template struct result; template struct result : fusion::result_of::at {}; template typename fusion::result_of::at::type operator ()(Cont &cont, N) const { return fusion::at(cont); } }; ////////////////////////////// actor >::type> const _1 = {{{}}}; actor >::type> const _2 = {{{}}}; actor >::type> const _3 = {{{}}}; ////////////////////////////// template<> struct eval_cases::case_ : when, at(_state, _value)> {}; ////////////////////////////// // Begin implementation of if_/else_ here // struct if_tag {}; struct else_tag {}; struct if_else_tag {}; template struct if_else_actor; // if_(x)[y] struct if_stmt : subscript, eval>, eval> {}; // if_(x)[y].else_[z] struct if_else_stmt : subscript< member, terminal > , eval > {}; typedef functional::make_expr make_if; typedef functional::make_expr make_if_else; typedef pod_generator make_if_else_actor; ////////////////////////////// struct if_else_generator : or_< // if_(this)[that] when< if_stmt // wrap in if_else_actor and unary if_tag expr , make_if_else_actor(make_if(_byval(_))) > // if_(this)[that].else_[other] , when< if_else_stmt // wrap in if_else_actor and unary if_else_tag expr , make_if_else_actor(make_if_else(_byval(_))) > , otherwise< make_if_else_actor(_) > > {}; ////////////////////////////// struct if_else_domain : domain {}; ////////////////////////////// struct complete_if_else_stmt : or_< unary_expr , unary_expr > {}; ////////////////////////////// template struct if_else_actor { typedef typename mpl::if_, phoenix_domain, if_else_domain>::type domain_; BOOST_PHOENIX_ACTOR(Expr, if_else_actor, domain_) // Declare a member named else_ that is a // terminal in if_else_domain. BOOST_PROTO_EXTENDS_MEMBERS_WITH_DOMAIN( ((else_tag, else_)) , if_else_domain ) }; // Function for evaluating lambdas like: if_(foo)[bar] struct if_eval : callable { typedef void result_type; template void operator()(I const & i, T const & t, S & s) const { if( eval()(i, s) ) eval()(t, s); } }; // Function for evaluating lambdas like: if_(foo)[bar].else_[baz] struct if_else_eval : callable { typedef void result_type; template void operator()(I const & i, T const & t, E const & e, S & s) const { if( eval()(i, s) ) eval()(t, s); else eval()(e, s); } }; ////////////////////////////// typedef functional::make_expr make_fun; template typename boost::result_of::type const if_(E const & e) { return make_fun()(if_tag(), ref(e)); } ////////////////////////////// // This tells Proto how to evaluate if_(x)[y] statements with if_eval template<> struct eval_cases::case_ : when< unary_expr , if_eval(_right(_left(_left)), _right(_left), _state) > {}; ////////////////////////////// // This tells Proto how to evaluate if(x)[y].else_[z] statements with if_else_eval template<> struct eval_cases::case_ : when< unary_expr , if_else_eval( _right(_left(_left(_left(_left(_left))))) , _right(_left(_left(_left(_left)))) , _right(_left) , _state ) > {}; } // namespace phoenix } // namespace boost #include using namespace boost; using namespace phoenix; int main() { int j = (_1 + _2)(1, 2); std::cout << j << "\n"; j = (_2 * 2)(1, 2); std::cout << j << "\n"; phoenix::if_(_1)[std::cout << _2 << "\n"] + _1; phoenix::if_(_1)[std::cout << _2 << "\n"](1,2,3); phoenix::if_(_1)[std::cout << _2 << "\n"].else_[std::cout << _3 << "\n"](1,2,3); phoenix::if_(_1)[std::cout << _2 << "\n"].else_[std::cout << _3 << "\n"](0,2,3); int x[] = { 1, 2, 3, 4 }; int y[] = { 2, 4, 6, 8 }; int z[4]; // Use a Phoenix lambda with std algorithms std::transform( x, x + 4, y, z, _1 * _2 ); }