#ifndef BOOST_PP_IS_ITERATING /////////////////////////////////////////////////////////////////////////////// /// \file make.hpp /// Contains definition of the make<> transform. // // 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_MAKE_HPP_EAN_12_02_2007 #define BOOST_PROTO_TRANSFORM_MAKE_HPP_EAN_12_02_2007 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace proto { namespace transform { namespace detail { using proto::detail::as_lvalue; template struct typelist { typedef void type; }; template::value> struct nested_type { typedef typename T::type type; }; template struct nested_type { typedef T type; }; template struct nested_type_if : nested_type {}; template::value > struct make_if_; template::value) > struct make_ { typedef R type; typedef void not_applied_; }; template struct make_if_ : make_ {}; #if BOOST_WORKAROUND(__GNUC__, == 3) // work around GCC bug template struct make_if_, Expr, State, Visitor, false> { typedef proto::expr type; typedef void not_applied_; }; #endif template struct make_if_ : boost::result_of {}; template::value> struct construct_ { typedef Type result_type; Type operator ()() const { return Type(); } #define TMP(Z, N, DATA) \ template \ Type operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a)) const \ { \ return Type(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \ } BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), TMP, ~) #undef TMP }; template struct construct_ { typedef Type result_type; Type operator ()() const { return Type(); } #define TMP(Z, N, DATA) \ template \ Type operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a)) const \ { \ Type that = {BOOST_PP_ENUM_PARAMS_Z(Z, N, a)}; \ return that; \ } BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), TMP, ~) #undef TMP }; #define TMP(Z, N, DATA) \ template \ Type construct(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a)) \ { \ return construct_()(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \ } BOOST_PP_REPEAT(BOOST_PROTO_MAX_ARITY, TMP, ~) #undef TMP } /// \brief A PrimitiveTransform which computes a type by evaluating any /// nested transforms and then constructs an object of that type. /// /// The make\<\> transform checks to see if \c Object is a template. /// If it is, the template type is disassembled to find nested transforms. /// Proto considers the following types to represent transforms: /// /// \li Function types /// \li Function pointer types /// \li Types for which proto::is_callable\< type \>::::value is \c true /// /// make\ \>::::result\::::type /// is evaluated as follows. For each \c X in X0,X1,..., do: /// /// \li If \c X is a template like U\, then let X' /// be make\ \>::::result\::::type /// (which evaluates this procedure recursively). Note whether any /// substitutions took place during this operation. /// \li Otherwise, if \c X is a transform, then let X' be /// when\<_, X\>::::result\::::type. /// Note that a substitution took place. /// \li Otherwise, let X' be \c X, and note that no substitution /// took place. /// \li If any substitutions took place in any of the above steps and /// T\ has a nested ::type typedef, /// the result type is T\::::type. /// \li Otherwise, the result type is T\. /// /// Note that when\<\> is implemented in terms of call\<\> /// and make\<\>, so the above procedure is evaluated recursively. template struct make : proto::callable { template struct result; template struct result { typedef typename detail::make_if_::type type; }; /// \param expr The current expression /// \param state The current state /// \param visitor An arbitrary visitor /// \return result\::::type() template typename result::type operator ()(Expr const &, State const &, Visitor &) const { typedef typename result::type result_type; return result_type(); } }; #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PROTO_MAX_ARITY, )) #include BOOST_PP_ITERATE() } /// INTERNAL ONLY /// template struct is_callable > : mpl::true_ {}; }} #endif #else #define N BOOST_PP_ITERATION() namespace detail { #if N > 0 template struct nested_type_if< T , typelist , typename typelist< BOOST_PP_ENUM_BINARY_PARAMS(N, typename A, ::not_applied_ BOOST_PP_INTERCEPT) >::type > { typedef T type; typedef void not_applied_; }; template< template class R BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A) , typename Expr, typename State, typename Visitor > struct make_, Expr, State, Visitor BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(N) > : nested_type_if< #define TMP0(Z, M, DATA) make_if_ #define TMP1(Z, M, DATA) typename TMP0(Z, M, DATA) ::type R , typelist #undef TMP0 #undef TMP1 > {}; #endif template< typename R BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A) , typename Expr, typename State, typename Visitor > struct make_if_ { typedef typename when<_, R(BOOST_PP_ENUM_PARAMS(N, A))>::template result::type type; }; template< typename R BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A) , typename Expr, typename State, typename Visitor > struct make_if_ { typedef typename when<_, R(BOOST_PP_ENUM_PARAMS(N, A))>::template result::type type; }; template struct construct_, true> { typedef proto::expr result_type; template result_type operator ()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_MAX(N, 1), A, &a)) const { return result_type::make(BOOST_PP_ENUM_PARAMS(BOOST_PP_MAX(N, 1), a)); } }; } /// \brief A PrimitiveTransform which computes a type by evaluating any /// nested transforms and then constructs an object of that type with the /// current expression, state and visitor, transformed according /// to \c A0 through \c AN. template struct make : proto::callable { template struct result; template struct result { /// \brief make\::::result\::::type typedef typename detail::make_if_::type type; }; /// Let \c ax be when\<_, Ax\>()(expr, state, visitor) /// for each \c x in [0,N]. /// Let \c T be result\::::type. /// Return T(a0, a1,... aN). /// /// \param expr The current expression /// \param state The current state /// \param visitor An arbitrary visitor template typename result::type operator ()(Expr const &expr, State const &state, Visitor &visitor) const { typedef typename result::type result_type; proto::detail::ignore_unused(expr); proto::detail::ignore_unused(state); proto::detail::ignore_unused(visitor); return detail::construct( #define TMP(Z, M, DATA) detail::as_lvalue(when<_, BOOST_PP_CAT(A, M)>()(expr, state, visitor)) BOOST_PP_ENUM(N, TMP, DATA) #undef TMP ); } }; #if BOOST_WORKAROUND(__GNUC__, == 3) // work around GCC bug template struct make(BOOST_PP_ENUM_PARAMS(N, A))> : proto::callable { template struct result; template struct result { typedef proto::expr type; }; template proto::expr operator ()(Expr const &expr, State const &state, Visitor &visitor) const { return proto::expr::make( #define TMP(Z, M, DATA) detail::as_lvalue(when<_, BOOST_PP_CAT(A, M)>()(expr, state, visitor)) BOOST_PP_ENUM(N, TMP, DATA) #undef TMP ); } }; #endif #undef N #endif