#ifndef BOOST_PP_IS_ITERATING /////////////////////////////////////////////////////////////////////////////// /// \file default.hpp /// Contains definition of the _default transform, which gives operators their /// usual C++ meanings and uses Boost.Typeof to deduce return types. // // 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) #ifndef BOOST_PROTO_TRANSFORM_DEFAULT_HPP_EAN_04_04_2008 #define BOOST_PROTO_TRANSFORM_DEFAULT_HPP_EAN_04_04_2008 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace proto { template struct _default : transform<_default > { template struct impl2; template struct impl2 : _value::impl {}; #define BOOST_PROTO_UNARY_OP_RESULT(OP, TAG, MAKE) \ template \ struct impl2 \ : transform_impl \ { \ private: \ typedef typename result_of::child_c::type e0; \ typedef typename Grammar::template impl::result_type r0; \ public: \ BOOST_PROTO_DECLTYPE_(OP proto::detail::MAKE(), result_type) \ result_type operator ()( \ typename impl2::expr_param e \ , typename impl2::state_param s \ , typename impl2::data_param d \ ) const \ { \ typename Grammar::template impl t0; \ return OP t0(proto::child_c<0>(e), s, d); \ } \ }; \ /**/ #define BOOST_PROTO_BINARY_OP_RESULT(OP, TAG, LMAKE, RMAKE) \ template \ struct impl2 \ : transform_impl \ { \ private: \ typedef typename result_of::child_c::type e0; \ typedef typename result_of::child_c::type e1; \ typedef typename Grammar::template impl::result_type r0; \ typedef typename Grammar::template impl::result_type r1; \ public: \ BOOST_PROTO_DECLTYPE_( \ proto::detail::LMAKE() OP proto::detail::RMAKE() \ , result_type \ ) \ result_type operator ()( \ typename impl2::expr_param e \ , typename impl2::state_param s \ , typename impl2::data_param d \ ) const \ { \ typename Grammar::template impl t0; \ typename Grammar::template impl t1; \ return t0(proto::child_c<0>(e), s, d) \ OP t1(proto::child_c<1>(e), s, d); \ } \ }; \ /**/ BOOST_PROTO_UNARY_OP_RESULT(+, tag::unary_plus, make) BOOST_PROTO_UNARY_OP_RESULT(-, tag::negate, make) BOOST_PROTO_UNARY_OP_RESULT(*, tag::dereference, make) BOOST_PROTO_UNARY_OP_RESULT(~, tag::complement, make) BOOST_PROTO_UNARY_OP_RESULT(&, tag::address_of, make) BOOST_PROTO_UNARY_OP_RESULT(!, tag::logical_not, make) BOOST_PROTO_UNARY_OP_RESULT(++, tag::pre_inc, make_mutable) BOOST_PROTO_UNARY_OP_RESULT(--, tag::pre_dec, make_mutable) BOOST_PROTO_BINARY_OP_RESULT(<<, tag::shift_left, make_mutable, make) BOOST_PROTO_BINARY_OP_RESULT(>>, tag::shift_right, make_mutable, make_mutable) BOOST_PROTO_BINARY_OP_RESULT(*, tag::multiplies, make, make) BOOST_PROTO_BINARY_OP_RESULT(/, tag::divides, make, make) BOOST_PROTO_BINARY_OP_RESULT(%, tag::modulus, make, make) BOOST_PROTO_BINARY_OP_RESULT(+, tag::plus, make, make) BOOST_PROTO_BINARY_OP_RESULT(-, tag::minus, make, make) BOOST_PROTO_BINARY_OP_RESULT(<, tag::less, make, make) BOOST_PROTO_BINARY_OP_RESULT(>, tag::greater, make, make) BOOST_PROTO_BINARY_OP_RESULT(<=, tag::less_equal, make, make) BOOST_PROTO_BINARY_OP_RESULT(>=, tag::greater_equal, make, make) BOOST_PROTO_BINARY_OP_RESULT(==, tag::equal_to, make, make) BOOST_PROTO_BINARY_OP_RESULT(!=, tag::not_equal_to, make, make) BOOST_PROTO_BINARY_OP_RESULT(||, tag::logical_or, make, make) BOOST_PROTO_BINARY_OP_RESULT(&&, tag::logical_and, make, make) BOOST_PROTO_BINARY_OP_RESULT(&, tag::bitwise_and, make, make) BOOST_PROTO_BINARY_OP_RESULT(|, tag::bitwise_or, make, make) BOOST_PROTO_BINARY_OP_RESULT(^, tag::bitwise_xor, make, make) BOOST_PROTO_BINARY_OP_RESULT(=, tag::assign, make_mutable, make) BOOST_PROTO_BINARY_OP_RESULT(<<=, tag::shift_left_assign, make_mutable, make) BOOST_PROTO_BINARY_OP_RESULT(>>=, tag::shift_right_assign, make_mutable, make) BOOST_PROTO_BINARY_OP_RESULT(*=, tag::multiplies_assign, make_mutable, make) BOOST_PROTO_BINARY_OP_RESULT(/=, tag::divides_assign, make_mutable, make) BOOST_PROTO_BINARY_OP_RESULT(%=, tag::modulus_assign, make_mutable, make) BOOST_PROTO_BINARY_OP_RESULT(+=, tag::plus_assign, make_mutable, make) BOOST_PROTO_BINARY_OP_RESULT(-=, tag::minus_assign, make_mutable, make) BOOST_PROTO_BINARY_OP_RESULT(&=, tag::bitwise_and_assign, make_mutable, make) BOOST_PROTO_BINARY_OP_RESULT(|=, tag::bitwise_or_assign, make_mutable, make) BOOST_PROTO_BINARY_OP_RESULT(^=, tag::bitwise_xor_assign, make_mutable, make) #undef BOOST_PROTO_UNARY_OP_RESULT #undef BOOST_PROTO_BINARY_OP_RESULT /// INTERNAL ONLY template struct is_member_function_invocation { typedef typename result_of::child_c::type e1; typedef typename Grammar::template impl::result_type r1; typedef typename remove_const::type>::type uncvref_r1; typedef typename is_member_function_pointer::type type; BOOST_STATIC_CONSTANT(bool, value = type::value); }; /// INTERNAL ONLY template struct memfun_impl : transform_impl { private: typedef typename result_of::child_c::type e0; typedef typename result_of::child_c::type e1; typedef typename Grammar::template impl::result_type r0; typedef typename Grammar::template impl::result_type r1; public: typedef typename detail::mem_ptr_fun::result_type result_type; result_type operator ()( typename memfun_impl::expr_param e , typename memfun_impl::state_param s , typename memfun_impl::data_param d ) const { typename Grammar::template impl t0; typename Grammar::template impl t1; return detail::mem_ptr_fun()( t0(proto::child_c<0>(e), s, d) , t1(proto::child_c<1>(e), s, d) ); } }; /// INTERNAL ONLY template struct memfun_impl : transform_impl { private: typedef typename result_of::child_c::type e0; typedef typename result_of::child_c::type e1; typedef typename Grammar::template impl::result_type r0; typedef typename Grammar::template impl::result_type r1; public: typedef detail::memfun result_type; result_type const operator ()( typename memfun_impl::expr_param e , typename memfun_impl::state_param s , typename memfun_impl::data_param d ) const { typename Grammar::template impl t0; typename Grammar::template impl t1; return detail::memfun( t0(proto::child_c<0>(e), s, d) , t1(proto::child_c<1>(e), s, d) ); } }; template struct impl2 : memfun_impl::value> {}; template struct impl2 : transform_impl { private: typedef typename result_of::child_c::type e0; typedef typename Grammar::template impl::result_type r0; public: BOOST_PROTO_DECLTYPE_(proto::detail::make_mutable() ++, result_type) result_type operator ()( typename impl2::expr_param e , typename impl2::state_param s , typename impl2::data_param d ) const { typename Grammar::template impl t0; return t0(proto::child_c<0>(e), s, d) ++; } }; template struct impl2 : transform_impl { private: typedef typename result_of::child_c::type e0; typedef typename Grammar::template impl::result_type r0; public: BOOST_PROTO_DECLTYPE_(proto::detail::make_mutable() --, result_type) result_type operator ()( typename impl2::expr_param e , typename impl2::state_param s , typename impl2::data_param d ) const { typename Grammar::template impl t0; return t0(proto::child_c<0>(e), s, d) --; } }; template struct impl2 : transform_impl { private: typedef typename result_of::child_c::type e0; typedef typename result_of::child_c::type e1; typedef typename Grammar::template impl::result_type r0; typedef typename Grammar::template impl::result_type r1; public: BOOST_PROTO_DECLTYPE_( proto::detail::make_subscriptable() [ proto::detail::make() ] , result_type ) result_type operator ()( typename impl2::expr_param e , typename impl2::state_param s , typename impl2::data_param d ) const { typename Grammar::template impl t0; typename Grammar::template impl t1; return t0(proto::child_c<0>(e), s, d) [ t1(proto::child_c<1>(e), s, d) ]; } }; template struct impl2 : transform_impl { private: typedef typename result_of::child_c::type e0; typedef typename result_of::child_c::type e1; typedef typename result_of::child_c::type e2; typedef typename Grammar::template impl::result_type r0; typedef typename Grammar::template impl::result_type r1; typedef typename Grammar::template impl::result_type r2; public: BOOST_PROTO_DECLTYPE_( proto::detail::make() ? proto::detail::make() : proto::detail::make() , result_type ) result_type operator ()( typename impl2::expr_param e , typename impl2::state_param s , typename impl2::data_param d ) const { typename Grammar::template impl t0; typename Grammar::template impl t1; typename Grammar::template impl t2; return t0(proto::child_c<0>(e), s, d) ? t1(proto::child_c<1>(e), s, d) : t2(proto::child_c<2>(e), s, d); } }; template struct impl2 : transform_impl { private: typedef typename result_of::child_c::type e0; typedef typename result_of::child_c::type e1; typedef typename Grammar::template impl::result_type r0; typedef typename Grammar::template impl::result_type r1; public: typedef typename proto::detail::comma_result::type result_type; result_type operator ()( typename impl2::expr_param e , typename impl2::state_param s , typename impl2::data_param d ) const { typename Grammar::template impl t0; typename Grammar::template impl t1; return t0(proto::child_c<0>(e), s, d) , t1(proto::child_c<1>(e), s, d); } }; #define EVAL_TYPE(Z, N, DATA) \ typedef \ typename result_of::child_c::type \ BOOST_PP_CAT(e, N); \ typedef \ typename Grammar::template impl::result_type \ BOOST_PP_CAT(r, N); \ /**/ #define EVAL(Z, N, DATA) \ typename Grammar::template impl()( \ proto::child_c(DATA), s, d \ ) \ /**/ template struct impl2 : transform_impl { EVAL_TYPE(~, 0, Expr) typedef typename proto::detail::result_of_fixup::type function_type; typedef typename boost::result_of::type result_type; result_type operator ()( typename impl2::expr_param e , typename impl2::state_param s , typename impl2::data_param d ) const { return EVAL(~, 0, e)(); } }; template struct impl2 : transform_impl { EVAL_TYPE(~, 0, Expr) EVAL_TYPE(~, 1, Expr) typedef typename proto::detail::result_of_fixup::type function_type; typedef typename detail::result_of_::type result_type; result_type operator ()( typename impl2::expr_param e , typename impl2::state_param s , typename impl2::data_param d ) const { return this->invoke( e , s , d , is_member_function_pointer() , is_member_object_pointer() ); } private: result_type invoke( typename impl2::expr_param e , typename impl2::state_param s , typename impl2::data_param d , mpl::false_ , mpl::false_ ) const { return EVAL(~, 0, e)(EVAL(~, 1, e)); } result_type invoke( typename impl2::expr_param e , typename impl2::state_param s , typename impl2::data_param d , mpl::true_ , mpl::false_ ) const { using namespace detail::get_pointer_; return (get_pointer(EVAL(~, 1, e)) ->* EVAL(~, 0, e))(); } result_type invoke( typename impl2::expr_param e , typename impl2::state_param s , typename impl2::data_param d , mpl::false_ , mpl::true_ ) const { using namespace detail::get_pointer_; return (get_pointer(EVAL(~, 1, e)) ->* EVAL(~, 0, e)); } }; #define BOOST_PP_ITERATION_PARAMS_1 (3, (3, BOOST_PROTO_MAX_ARITY, )) #include BOOST_PP_ITERATE() #undef EVAL_TYPE #undef EVAL template struct impl : impl2< Expr , State , Data , typename transform_impl::expr::proto_tag , transform_impl::expr::proto_arity_c > {}; }; template struct is_callable<_default > : mpl::true_ {}; }} #endif #else #define N BOOST_PP_ITERATION() template struct impl2 : transform_impl { BOOST_PP_REPEAT(N, EVAL_TYPE, Expr) typedef typename proto::detail::result_of_fixup::type function_type; typedef typename boost::result_of< function_type(BOOST_PP_ENUM_SHIFTED_PARAMS(N, r)) >::type result_type; result_type operator ()( typename impl2::expr_param e , typename impl2::state_param s , typename impl2::data_param d ) const { return this->invoke(e, s, d, is_member_function_pointer()); } private: result_type invoke( typename impl2::expr_param e , typename impl2::state_param s , typename impl2::data_param d , mpl::false_ ) const { return EVAL(~, 0, e)(BOOST_PP_ENUM_SHIFTED(N, EVAL, e)); } result_type invoke( typename impl2::expr_param e , typename impl2::state_param s , typename impl2::data_param d , mpl::true_ ) const { #define M0(Z, M, e) BOOST_PP_COMMA_IF(BOOST_PP_SUB(M, 2)) EVAL(Z, M, e) using namespace detail::get_pointer_; return (get_pointer(EVAL(~, 1, e)) ->* EVAL(~, 0, e))( BOOST_PP_REPEAT_FROM_TO(2, N, M0, e) ); #undef M0 } }; #undef N #endif