#ifndef BOOST_PP_IS_ITERATING /////////////////////////////////////////////////////////////////////////////// /// \file make_expr.hpp /// Given a Fusion sequence of arguments and the type of a proto Expression, /// unpacks the sequence into the Expression. // // Copyright 2007 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_MAKE_EXPR_HPP_EAN_04_01_2005 #define BOOST_PROTO_MAKE_EXPR_HPP_EAN_04_01_2005 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if BOOST_VERSION >= 103500 # include # include # include namespace boost { namespace proto { namespace detail { namespace fusion_ = fusion; }}} #else # include # include # include namespace boost { namespace proto { namespace detail { namespace fusion_ { namespace result_of = fusion::meta; template typename result_of::at_c::type at_c(Seq &seq) { return fusion::at(seq); } template typename result_of::at_c::type at_c(Seq const &seq) { return fusion::at(seq); } }}}} #endif #include /// INTERNAL ONLY /// #define BOOST_PROTO_AS_ARG_TYPE(Z, N, DATA) \ typename boost::proto::result_of::as_arg< \ BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, DATA), N) \ , BOOST_PP_TUPLE_ELEM(2, 1, DATA) \ >::type \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_AS_ARG(Z, N, DATA) \ boost::proto::as_arg( \ BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, DATA), N) \ ) \ /**/ /// INTERNAL ONLY /// # define BOOST_PROTO_AT_TYPE(Z, N, DATA) \ typename remove_reference< \ typename detail::fusion_::result_of::value_at_c::type \ >::type \ /**/ /// INTERNAL ONLY /// # define BOOST_PROTO_AT(Z, N, DATA) \ detail::fusion_::at_c(BOOST_PP_TUPLE_ELEM(2, 0, DATA)) \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_AS_ARG_AT_TYPE(Z, N, DATA) \ typename boost::proto::result_of::as_arg< \ BOOST_PROTO_AT_TYPE(Z, N, DATA) \ , BOOST_PP_TUPLE_ELEM(2, 1, DATA) \ >::type \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_AS_ARG_AT(Z, N, DATA) \ boost::proto::as_arg( \ BOOST_PROTO_AT(Z, N, DATA) \ ) \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_VARARG_TEMPLATE_AUX_(R, DATA, I, ELEM) \ (ELEM BOOST_PP_CAT(BOOST_PP_CAT(X, DATA), BOOST_PP_CAT(_, I))) \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_VARARG_TEMPLATE_YES_(R, DATA, I, ELEM) \ BOOST_PP_LIST_FOR_EACH_I_R( \ R \ , BOOST_PROTO_VARARG_TEMPLATE_AUX_ \ , I \ , BOOST_PP_TUPLE_TO_LIST( \ BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ELEM)) \ , BOOST_PP_SEQ_TO_TUPLE(BOOST_PP_SEQ_TAIL(ELEM)) \ ) \ ) \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_VARARG_TEMPLATE_NO_(R, DATA, I, ELEM) \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_VARARG_TEMPLATE_(R, DATA, I, ELEM) \ BOOST_PP_IF( \ BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ELEM)) \ , BOOST_PROTO_VARARG_TEMPLATE_YES_ \ , BOOST_PROTO_VARARG_TEMPLATE_NO_ \ )(R, DATA, I, ELEM) \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_VARARG_TYPE_AUX_(R, DATA, I, ELEM) \ (BOOST_PP_CAT(BOOST_PP_CAT(X, DATA), BOOST_PP_CAT(_, I))) \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_TEMPLATE_PARAMS_YES_(R, DATA, I, ELEM) \ < \ BOOST_PP_SEQ_ENUM( \ BOOST_PP_LIST_FOR_EACH_I_R( \ R \ , BOOST_PROTO_VARARG_TYPE_AUX_ \ , I \ , BOOST_PP_TUPLE_TO_LIST( \ BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ELEM)) \ , BOOST_PP_SEQ_TO_TUPLE(BOOST_PP_SEQ_TAIL(ELEM)) \ ) \ ) \ ) \ > \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_TEMPLATE_PARAMS_NO_(R, DATA, I, ELEM) \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_VARARG_TYPE_(R, DATA, I, ELEM) \ BOOST_PP_COMMA_IF(I) \ BOOST_PP_SEQ_HEAD(ELEM) \ BOOST_PP_IF( \ BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ELEM)) \ , BOOST_PROTO_TEMPLATE_PARAMS_YES_ \ , BOOST_PROTO_TEMPLATE_PARAMS_NO_ \ )(R, DATA, I, ELEM) BOOST_PP_EXPR_IF(BOOST_PP_GREATER(I, 1), const) \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_VARARG_AS_EXPR_(R, DATA, I, ELEM) \ BOOST_PP_EXPR_IF( \ BOOST_PP_GREATER(I, 1) \ , (( \ BOOST_PP_SEQ_HEAD(ELEM) \ BOOST_PP_IF( \ BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ELEM)) \ , BOOST_PROTO_TEMPLATE_PARAMS_YES_ \ , BOOST_PROTO_TEMPLATE_PARAMS_NO_ \ )(R, DATA, I, ELEM)() \ )) \ ) \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_VARARG_AS_ARG_(Z, N, DATA) \ (BOOST_PP_CAT(DATA, N)) \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_SEQ_PUSH_FRONT(SEQ, ELEM) \ BOOST_PP_SEQ_POP_BACK(BOOST_PP_SEQ_PUSH_FRONT(BOOST_PP_SEQ_PUSH_BACK(SEQ, _dummy_), ELEM)) \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_VARARG_AS_PARAM_(Z, N, DATA) \ (BOOST_PP_CAT(DATA, N)) \ /**/ /// INTERNAL ONLY /// #define BOOST_PROTO_VARARG_FUN_(Z, N, DATA) \ template< \ BOOST_PP_SEQ_ENUM( \ BOOST_PP_SEQ_FOR_EACH_I( \ BOOST_PROTO_VARARG_TEMPLATE_, ~ \ , BOOST_PP_SEQ_PUSH_FRONT( \ BOOST_PROTO_SEQ_PUSH_FRONT( \ BOOST_PP_TUPLE_ELEM(4, 2, DATA) \ , (BOOST_PP_TUPLE_ELEM(4, 3, DATA)) \ ) \ , BOOST_PP_TUPLE_ELEM(4, 1, DATA) \ ) \ ) \ BOOST_PP_REPEAT_ ## Z(N, BOOST_PROTO_VARARG_AS_PARAM_, typename A) \ ) \ > \ typename boost::proto::result_of::make_expr< \ BOOST_PP_SEQ_FOR_EACH_I( \ BOOST_PROTO_VARARG_TYPE_, ~ \ , BOOST_PP_SEQ_PUSH_FRONT( \ BOOST_PROTO_SEQ_PUSH_FRONT( \ BOOST_PP_TUPLE_ELEM(4, 2, DATA) \ , (BOOST_PP_TUPLE_ELEM(4, 3, DATA)) \ ) \ , BOOST_PP_TUPLE_ELEM(4, 1, DATA) \ ) \ ) \ BOOST_PP_ENUM_TRAILING_PARAMS(N, const A) \ >::type const \ BOOST_PP_TUPLE_ELEM(4, 0, DATA)(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, const A, &a)) \ { \ return boost::proto::result_of::make_expr< \ BOOST_PP_SEQ_FOR_EACH_I( \ BOOST_PROTO_VARARG_TYPE_, ~ \ , BOOST_PP_SEQ_PUSH_FRONT( \ BOOST_PROTO_SEQ_PUSH_FRONT( \ BOOST_PP_TUPLE_ELEM(4, 2, DATA) \ , (BOOST_PP_TUPLE_ELEM(4, 3, DATA)) \ ) \ , BOOST_PP_TUPLE_ELEM(4, 1, DATA) \ ) \ ) \ BOOST_PP_ENUM_TRAILING_PARAMS(N, const A) \ >::call( \ BOOST_PP_SEQ_ENUM( \ BOOST_PP_SEQ_FOR_EACH_I( \ BOOST_PROTO_VARARG_AS_EXPR_, ~ \ , BOOST_PP_SEQ_PUSH_FRONT( \ BOOST_PROTO_SEQ_PUSH_FRONT( \ BOOST_PP_TUPLE_ELEM(4, 2, DATA) \ , (BOOST_PP_TUPLE_ELEM(4, 3, DATA)) \ ) \ , BOOST_PP_TUPLE_ELEM(4, 1, DATA) \ ) \ ) \ BOOST_PP_REPEAT_ ## Z(N, BOOST_PROTO_VARARG_AS_ARG_, a) \ ) \ ); \ } \ /**/ /// \code /// BOOST_PROTO_DEFINE_FUNCTION_TEMPLATE( /// 1 /// , construct /// , boost::proto::default_domain /// , (boost::proto::tag::function) /// , ((op::construct)(typename)(int)) /// ) /// \endcode #define BOOST_PROTO_DEFINE_FUNCTION_TEMPLATE(ARGCOUNT, NAME, DOMAIN, TAG, BOUNDARGS) \ BOOST_PP_REPEAT_FROM_TO( \ ARGCOUNT \ , BOOST_PP_INC(ARGCOUNT) \ , BOOST_PROTO_VARARG_FUN_ \ , (NAME, TAG, BOUNDARGS, DOMAIN) \ )\ /**/ /// \code /// BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE( /// construct /// , boost::proto::default_domain /// , (boost::proto::tag::function) /// , ((op::construct)(typename)(int)) /// ) /// \endcode #define BOOST_PROTO_DEFINE_VARARG_FUNCTION_TEMPLATE(NAME, DOMAIN, TAG, BOUNDARGS) \ BOOST_PP_REPEAT( \ BOOST_PP_SUB(BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), BOOST_PP_SEQ_SIZE(BOUNDARGS)) \ , BOOST_PROTO_VARARG_FUN_ \ , (NAME, TAG, BOUNDARGS, DOMAIN) \ ) \ /**/ namespace boost { namespace fusion { template class unfused_generic; }} namespace boost { namespace proto { namespace detail { template< typename Domain BOOST_PP_ENUM_TRAILING_BINARY_PARAMS( BOOST_PROTO_MAX_ARITY , typename A , = default_domain BOOST_PP_INTERCEPT ) > struct deduce_domain_ { typedef Domain type; }; template struct deduce_domain_< default_domain BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A) > : deduce_domain_< typename domain_of::type , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PROTO_MAX_ARITY, A) > {}; template<> struct deduce_domain_ { typedef default_domain type; }; template struct unpack_expr_ {}; template struct unpack_expr_ { typedef expr< tag::terminal , args0::type> > expr_type; typedef typename Domain::template apply::type type; static type const call(Sequence const &sequence) { expr_type that = {fusion_::at_c<0>(sequence)}; return Domain::make(that); } }; template struct unpack_expr_ : unpack_expr_ {}; template< typename Tag , typename Domain BOOST_PP_ENUM_TRAILING_BINARY_PARAMS( BOOST_PROTO_MAX_ARITY , typename A , = void BOOST_PP_INTERCEPT ) , typename _ = void > struct make_expr_ {}; template struct make_expr_ { typedef typename add_reference::type reference; typedef expr > expr_type; typedef typename Domain::template apply::type type; static type const call(reference a) { expr_type that = {a}; return Domain::make(that); } }; #define BOOST_PP_ITERATION_PARAMS_1 \ (4, (1, BOOST_PROTO_MAX_ARITY, , 1)) \ /**/ #include BOOST_PP_ITERATE() } namespace result_of { template struct unpack_expr : detail::unpack_expr_< Tag , deduce_domain , Sequence , detail::fusion_::result_of::size::type::value > {}; template struct unpack_expr : detail::unpack_expr_< Tag , Domain , Sequence , detail::fusion_::result_of::size::type::value > {}; template< typename Tag BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, typename A) , typename , typename > struct make_expr : make_expr< Tag , deduce_domain BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A) > {}; template< typename Tag , typename Domain BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, typename A) > struct make_expr< Tag , Domain BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A) , typename Domain::proto_is_domain_ > : detail::make_expr_< Tag , Domain BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A) > {}; template< typename Tag BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, typename A) > struct make_expr< Tag , deduce_domain BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A) , void > : detail::make_expr_< Tag , typename detail::deduce_domain_< typename domain_of::type , BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PROTO_MAX_ARITY, A) >::type BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A) > {}; } namespace functional { template struct make_expr { template struct result {}; template typename result_of::make_expr::type const operator ()(A &a) const { return result_of::make_expr::call(a); } #define BOOST_PP_ITERATION_PARAMS_1 \ (4, (1, BOOST_PROTO_MAX_ARITY, , 2)) \ /**/ #include BOOST_PP_ITERATE() }; template struct make_expr { template struct result {}; template struct result : result_of::make_expr {}; template typename result_of::make_expr::type operator ()(A &a) const { return result_of::make_expr::call(a); } template typename result_of::make_expr::type operator ()(A const &a) const { return result_of::make_expr::call(a); } }; template struct unpack_expr { template struct result {}; template struct result : result_of::unpack_expr< Tag , Domain , typename detail::remove_cv_ref::type > {}; template typename result_of::unpack_expr::type operator ()(Sequence const &sequence) const { return result_of::unpack_expr::call(sequence); } }; template struct unfused_expr_fun { template struct result : result_of::unpack_expr {}; template typename proto::result_of::unpack_expr::type operator ()(Sequence const &sequence) const { return result_of::unpack_expr::call(sequence); } }; template struct unfused_expr : fusion::unfused_generic > {}; } /// unpack_expr /// template typename lazy_disable_if< is_domain , result_of::unpack_expr >::type const unpack_expr(Sequence const &sequence) { return result_of::unpack_expr::call(sequence); } /// \overload /// template typename result_of::unpack_expr::type const unpack_expr(Sequence2 const &sequence2) { return result_of::unpack_expr::call(sequence2); } /// make_expr /// template typename lazy_disable_if< is_domain , result_of::make_expr >::type const make_expr(A0 &a0 BOOST_PROTO_DISABLE_IF_IS_CONST(A0)) { return result_of::make_expr::call(a0); } /// \overload /// template typename result_of::make_expr::type const make_expr(B0 &b0 BOOST_PROTO_DISABLE_IF_IS_CONST(B0)) { return result_of::make_expr::call(b0); } #define BOOST_PP_ITERATION_PARAMS_1 \ (4, (1, BOOST_PROTO_MAX_ARITY, , 3)) \ /**/ #include BOOST_PP_ITERATE() }} #undef BOOST_PROTO_AT #undef BOOST_PROTO_AT_TYPE #undef BOOST_PROTO_AS_ARG_AT #undef BOOST_PROTO_AS_ARG_AT_TYPE #endif // BOOST_PROTO_MAKE_EXPR_HPP_EAN_04_01_2005 #elif BOOST_PP_ITERATION_FLAGS() == 1 #define N BOOST_PP_ITERATION() #define M BOOST_PP_SUB(BOOST_PROTO_MAX_ARITY, N) template struct make_expr_ { typedef expr< Tag , BOOST_PP_CAT(args, N) > expr_type; typedef typename Domain::template apply::type type; static type const call(BOOST_PP_ENUM_BINARY_PARAMS(N, A, &a)) { expr_type that = { BOOST_PP_ENUM(N, BOOST_PROTO_AS_ARG, (a, Domain)) }; return Domain::make(that); } }; template struct unpack_expr_ { typedef expr< Tag , BOOST_PP_CAT(args, N)< BOOST_PP_ENUM(N, BOOST_PROTO_AS_ARG_AT_TYPE, (Sequence const, Domain)) > > expr_type; typedef typename Domain::template apply::type type; static type const call(Sequence const &sequence) { expr_type that = { BOOST_PP_ENUM(N, BOOST_PROTO_AS_ARG_AT, (sequence, Domain)) }; return Domain::make(that); } }; template struct unpack_expr_ : unpack_expr_< Tag , typename detail::deduce_domain_< typename domain_of< BOOST_PROTO_AT_TYPE(~, 0, (Sequence const, ~)) >::type BOOST_PP_COMMA_IF(BOOST_PP_DEC(N)) BOOST_PP_ENUM_SHIFTED(N, BOOST_PROTO_AT_TYPE, (Sequence const, ~)) >::type , Sequence , N > {}; #undef N #undef M #elif BOOST_PP_ITERATION_FLAGS() == 2 #define N BOOST_PP_ITERATION() template struct result : result_of::make_expr< Tag , Domain BOOST_PP_ENUM_TRAILING_BINARY_PARAMS( N , typename remove_reference::type BOOST_PP_INTERCEPT ) > {}; template typename result_of::make_expr< Tag , Domain BOOST_PP_ENUM_TRAILING_PARAMS(N, const A) >::type const operator ()(BOOST_PP_ENUM_BINARY_PARAMS(N, const A, &a)) const { return result_of::make_expr ::call(BOOST_PP_ENUM_PARAMS(N, a)); } #undef N #elif BOOST_PP_ITERATION_FLAGS() == 3 #define N BOOST_PP_ITERATION() /// \overload /// template typename lazy_disable_if< is_domain , result_of::make_expr >::type const make_expr(BOOST_PP_ENUM_BINARY_PARAMS(N, const A, &a)) { return result_of::make_expr ::call(BOOST_PP_ENUM_PARAMS(N, a)); } /// \overload /// template typename result_of::make_expr< Tag , Domain BOOST_PP_ENUM_TRAILING_PARAMS(N, const B) >::type const make_expr(BOOST_PP_ENUM_BINARY_PARAMS(N, const B, &b)) { return result_of::make_expr ::call(BOOST_PP_ENUM_PARAMS(N, b)); } #undef N #endif // BOOST_PP_IS_ITERATING