boost/xpressive/proto/op_base.hpp
/////////////////////////////////////////////////////////////////////////////// /// \file op_base.hpp /// Contains definitions of unary_op\<\>, binary_op\<\> and nary_op\<\>, /// as well as the is_op\<\> and the make_op() helper function. // // Copyright 2004 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_OP_BASE_HPP_EAN_04_01_2005 #define BOOST_PROTO_OP_BASE_HPP_EAN_04_01_2005 #include <boost/mpl/if.hpp> #include <boost/mpl/or.hpp> #include <boost/preprocessor/arithmetic/inc.hpp> #include <boost/preprocessor/facilities/intercept.hpp> #include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_trailing_params.hpp> #include <boost/preprocessor/repetition/enum_binary_params.hpp> #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp> #include <boost/preprocessor/repetition/repeat.hpp> #include <boost/preprocessor/repetition/repeat_from_to.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/type_traits/is_base_and_derived.hpp> #include <boost/spirit/fusion/sequence/tuple.hpp> #include <boost/xpressive/proto/proto_fwd.hpp> #include <boost/xpressive/proto/arg_traits.hpp> namespace boost { namespace proto { /////////////////////////////////////////////////////////////////////////////// // op_root struct op_root { }; /////////////////////////////////////////////////////////////////////////////// // is_proxy template<typename T> struct is_proxy : mpl::false_ { }; template<typename Op, typename Param> struct is_proxy<op_proxy<Op, Param> > : mpl::true_ { }; /////////////////////////////////////////////////////////////////////////////// // is_op template<typename T> struct is_op : mpl::or_<is_proxy<T>, is_base_and_derived<op_root, T> > { }; /////////////////////////////////////////////////////////////////////////////// // as_op template<typename Op> struct as_op<Op, true> { typedef typename Op::type type; static typename Op::const_reference make(Op const &op) { return op.cast(); } }; template<typename T> struct as_op<T, false> { typedef unary_op<T, noop_tag> type; static type const make(T const &t) { return noop(t); } }; // These operators must be members. #define BOOST_PROTO_DEFINE_MEMBER_OPS() \ template<typename Arg> \ binary_op<Op, typename as_op<Arg>::type, assign_tag> const \ operator =(Arg const &arg) const \ { \ return make_op<assign_tag>(this->cast(), as_op<Arg>::make(arg)); \ } \ template<typename Arg> \ binary_op<Op, typename as_op<Arg>::type, subscript_tag> const \ operator [](Arg const &arg) const \ { \ return make_op<subscript_tag>(this->cast(), as_op<Arg>::make(arg)); \ } \ nary_op<Op> operator ()() const \ { \ return nary_op<Op>(this->cast()); \ } \ BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), BOOST_PROTO_FUN_OP, _) #define BOOST_PROTO_FUN_OP(z, n, _) \ template<BOOST_PP_ENUM_PARAMS_Z(z, n, typename A)> \ nary_op<Op BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, A)> \ operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, const &a)) const \ { \ return nary_op<Op BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, A)> \ (this->cast() BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, a)); \ } /////////////////////////////////////////////////////////////////////////////// // op_base template<typename Op> struct op_base : op_root { typedef Op type; typedef type const &const_reference; Op &cast() { return *static_cast<Op *>(this); } Op const &cast() const { return *static_cast<Op const *>(this); } BOOST_PROTO_DEFINE_MEMBER_OPS() }; /////////////////////////////////////////////////////////////////////////////// // unary_op template<typename Arg, typename Tag> struct unary_op : op_base<unary_op<Arg, Tag> > { typedef typename value_type<Arg>::type arg_type; typedef Tag tag_type; arg_type arg; unary_op() : arg() {} explicit unary_op(typename call_traits<Arg>::param_type arg_) : arg(arg_) {} using op_base<unary_op<Arg, Tag> >::operator =; }; /////////////////////////////////////////////////////////////////////////////// // binary_op template<typename Left, typename Right, typename Tag> struct binary_op : op_base<binary_op<Left, Right, Tag> > { typedef typename value_type<Left>::type left_type; typedef typename value_type<Right>::type right_type; typedef Tag tag_type; left_type left; right_type right; binary_op() : left() , right() {} binary_op( typename call_traits<Left>::param_type left_ , typename call_traits<Right>::param_type right_) : left(left_) , right(right_) {} using op_base<binary_op<Left, Right, Tag> >::operator =; }; /////////////////////////////////////////////////////////////////////////////// // nary_op template<typename Fun, BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_ARITY, typename A)> struct nary_op : op_base<nary_op<Fun, BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_ARITY, A)> > { typedef function_tag tag_type; typedef Fun functor_type; typedef fusion::tuple< BOOST_PP_ENUM_BINARY_PARAMS( BOOST_PROTO_MAX_ARITY, typename value_type<A, >::type BOOST_PP_INTERCEPT) > args_type; functor_type functor; args_type args; nary_op() : functor() , args() {} #define BOOST_PROTO_NARY_OP_CTOR(z, n, _) \ nary_op( \ typename call_traits<Fun>::param_type fun \ BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(z, n, typename call_traits<A, >::param_type a))\ : functor(fun) \ , args(BOOST_PP_ENUM_PARAMS_Z(z, n, a)) \ {} BOOST_PP_REPEAT(BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), BOOST_PROTO_NARY_OP_CTOR, _) #undef BOOST_PROTO_NARY_OP_CTOR using op_base<nary_op<Fun, BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_ARITY, A)> >::operator =; }; /////////////////////////////////////////////////////////////////////////////// // op_proxy template<typename Op, typename Param> struct op_proxy { typedef Op type; typedef type const const_reference; Param param_; Op const cast() const { return Op(this->param_); } operator Op const() const { return this->cast(); } BOOST_PROTO_DEFINE_MEMBER_OPS() }; template<typename Op> struct op_proxy<Op, void> { typedef Op type; typedef type const const_reference; Op const cast() const { return Op(); } operator Op const() const { return this->cast(); } BOOST_PROTO_DEFINE_MEMBER_OPS() }; /////////////////////////////////////////////////////////////////////////////// // make_op template<typename Op, typename Arg> unary_op<Arg, Op> const make_op(Arg const &arg) { return unary_op<Arg, Op>(arg); } /////////////////////////////////////////////////////////////////////////////// // make_op template<typename Op, typename Left, typename Right> binary_op<Left, Right, Op> const make_op(Left const &left, Right const &right) { return binary_op<Left, Right, Op>(left, right); } }} #endif