Chris@16: #if !defined(BOOST_PROTO_DONT_USE_PREPROCESSED_FILES) Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES Chris@16: #include Chris@16: #else Chris@16: #include Chris@16: #endif Chris@16: Chris@16: #elif !defined(BOOST_PP_IS_ITERATING) Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: #define BOOST_PROTO_CHILD(Z, N, DATA) \ Chris@16: typedef BOOST_PP_CAT(Arg, N) BOOST_PP_CAT(proto_child, N); \ Chris@16: BOOST_PP_CAT(proto_child, N) BOOST_PP_CAT(child, N); \ Chris@16: /**< INTERNAL ONLY */ Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: #define BOOST_PROTO_VOID(Z, N, DATA) \ Chris@16: typedef void BOOST_PP_CAT(proto_child, N); \ Chris@16: /**< INTERNAL ONLY */ Chris@16: Chris@16: // Generate variadic versions of expr Chris@16: #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES) Chris@16: #pragma wave option(preserve: 2, line: 0, output: "preprocessed/expr_variadic.hpp") Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: /// \file expr_variadic.hpp Chris@16: /// Contains definition of expr\<\> class template. Chris@16: // Chris@16: // Copyright 2008 Eric Niebler. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES) Chris@16: #pragma wave option(preserve: 1) Chris@16: #endif Chris@16: Chris@16: // The expr<> specializations are actually defined here. Chris@16: #define BOOST_PROTO_DEFINE_TERMINAL Chris@16: #define BOOST_PP_ITERATION_PARAMS_1 \ Chris@16: (3, (0, 0, )) Chris@16: #include BOOST_PP_ITERATE() Chris@16: Chris@16: #undef BOOST_PROTO_DEFINE_TERMINAL Chris@16: #define BOOST_PP_ITERATION_PARAMS_1 \ Chris@16: (3, (1, BOOST_PROTO_MAX_ARITY, )) Chris@16: #include BOOST_PP_ITERATE() Chris@16: Chris@16: // Generate non-variadic versions of expr Chris@16: #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES) Chris@16: #define BOOST_NO_CXX11_VARIADIC_TEMPLATES Chris@16: #pragma wave option(preserve: 2, line: 0, output: "preprocessed/expr.hpp") Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: /// \file expr.hpp Chris@16: /// Contains definition of expr\<\> class template. Chris@16: // Chris@16: // Copyright 2008 Eric Niebler. Distributed under the Boost Chris@16: // Software License, Version 1.0. (See accompanying file Chris@16: // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #pragma wave option(preserve: 1) Chris@16: Chris@16: // The expr<> specializations are actually defined here. Chris@16: #define BOOST_PROTO_DEFINE_TERMINAL Chris@16: #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 0, )) Chris@16: #include BOOST_PP_ITERATE() Chris@16: Chris@16: #undef BOOST_PROTO_DEFINE_TERMINAL Chris@16: #define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PROTO_MAX_ARITY, )) Chris@16: #include BOOST_PP_ITERATE() Chris@16: Chris@16: #pragma wave option(output: null) Chris@16: #undef BOOST_NO_CXX11_VARIADIC_TEMPLATES Chris@16: #endif Chris@16: Chris@16: #undef BOOST_PROTO_CHILD Chris@16: #undef BOOST_PROTO_VOID Chris@16: Chris@16: #else Chris@16: Chris@16: #define ARG_COUNT BOOST_PP_MAX(1, BOOST_PP_ITERATION()) Chris@16: Chris@16: /// \brief Representation of a node in an expression tree. Chris@16: /// Chris@16: /// \c proto::expr\<\> is a node in an expression template tree. It Chris@16: /// is a container for its child sub-trees. It also serves as Chris@16: /// the terminal nodes of the tree. Chris@16: /// Chris@16: /// \c Tag is type that represents the operation encoded by Chris@16: /// this expression. It is typically one of the structs Chris@16: /// in the \c boost::proto::tag namespace, but it doesn't Chris@16: /// have to be. Chris@16: /// Chris@16: /// \c Args is a type list representing the type of the children Chris@16: /// of this expression. It is an instantiation of one Chris@16: /// of \c proto::list1\<\>, \c proto::list2\<\>, etc. The Chris@16: /// child types must all themselves be either \c expr\<\> Chris@16: /// or proto::expr\<\>&. If \c Args is an Chris@16: /// instantiation of \c proto::term\<\> then this Chris@16: /// \c expr\<\> type represents a terminal expression; Chris@16: /// the parameter to the \c proto::term\<\> template Chris@16: /// represents the terminal's value type. Chris@16: /// Chris@16: /// \c Arity is an integral constant representing the number of child Chris@16: /// nodes this node contains. If \c Arity is 0, then this Chris@16: /// node is a terminal. Chris@16: /// Chris@16: /// \c proto::expr\<\> is a valid Fusion random-access sequence, where Chris@16: /// the elements of the sequence are the child expressions. Chris@16: #ifdef BOOST_PROTO_DEFINE_TERMINAL Chris@16: template Chris@16: struct expr, 0> Chris@16: #else Chris@16: template Chris@16: struct expr, BOOST_PP_ITERATION() > Chris@16: #endif Chris@16: { Chris@16: typedef Tag proto_tag; Chris@16: static const long proto_arity_c = BOOST_PP_ITERATION(); Chris@16: typedef mpl::long_ proto_arity; Chris@16: typedef expr proto_base_expr; Chris@16: #ifdef BOOST_PROTO_DEFINE_TERMINAL Chris@16: typedef term proto_args; Chris@16: #else Chris@16: typedef BOOST_PP_CAT(list, BOOST_PP_ITERATION()) proto_args; Chris@16: #endif Chris@16: typedef basic_expr proto_grammar; Chris@16: typedef default_domain proto_domain; Chris@16: typedef default_generator proto_generator; Chris@16: typedef proto::tag::proto_expr fusion_tag; Chris@16: typedef expr proto_derived_expr; Chris@16: typedef void proto_is_expr_; /**< INTERNAL ONLY */ Chris@16: Chris@16: BOOST_PP_REPEAT(ARG_COUNT, BOOST_PROTO_CHILD, ~) Chris@16: BOOST_PP_REPEAT_FROM_TO(ARG_COUNT, BOOST_PROTO_MAX_ARITY, BOOST_PROTO_VOID, ~) Chris@16: Chris@16: /// \return *this Chris@16: /// Chris@16: BOOST_FORCEINLINE Chris@16: expr const &proto_base() const Chris@16: { Chris@16: return *this; Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: BOOST_FORCEINLINE Chris@16: expr &proto_base() Chris@16: { Chris@16: return *this; Chris@16: } Chris@16: Chris@16: #ifdef BOOST_PROTO_DEFINE_TERMINAL Chris@16: /// \return A new \c expr\<\> object initialized with the specified Chris@16: /// arguments. Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: static expr const make(A0 &a0) Chris@16: { Chris@16: return detail::make_terminal(a0, static_cast(0), static_cast(0)); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: static expr const make(A0 const &a0) Chris@16: { Chris@16: return detail::make_terminal(a0, static_cast(0), static_cast(0)); Chris@16: } Chris@16: #else Chris@16: /// \return A new \c expr\<\> object initialized with the specified Chris@16: /// arguments. Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: static expr const make(BOOST_PP_ENUM_BINARY_PARAMS(ARG_COUNT, A, const &a)) Chris@16: { Chris@16: expr that = {BOOST_PP_ENUM_PARAMS(ARG_COUNT, a)}; Chris@16: return that; Chris@16: } Chris@16: #endif Chris@16: Chris@16: #if 1 == BOOST_PP_ITERATION() Chris@16: /// If \c Tag is \c boost::proto::tag::address_of and \c proto_child0 is Chris@16: /// T&, then \c address_of_hack_type_ is T*. Chris@16: /// Otherwise, it is some undefined type. Chris@16: typedef typename detail::address_of_hack::type address_of_hack_type_; Chris@16: Chris@16: /// \return The address of this->child0 if \c Tag is Chris@16: /// \c boost::proto::tag::address_of. Otherwise, this function will Chris@16: /// fail to compile. Chris@16: /// Chris@16: /// \attention Proto overloads operator&, which means that Chris@16: /// proto-ified objects cannot have their addresses taken, unless we use Chris@16: /// the following hack to make \c &x implicitly convertible to \c X*. Chris@16: BOOST_FORCEINLINE Chris@16: operator address_of_hack_type_() const Chris@16: { Chris@16: return boost::addressof(this->child0); Chris@16: } Chris@16: #else Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: typedef detail::not_a_valid_type address_of_hack_type_; Chris@16: #endif Chris@16: Chris@16: /// Assignment Chris@16: /// Chris@16: /// \param a The rhs. Chris@16: /// \return A new \c expr\<\> node representing an assignment of \c that to \c *this. Chris@16: BOOST_FORCEINLINE Chris@16: proto::expr< Chris@16: proto::tag::assign Chris@16: , list2 Chris@16: , 2 Chris@16: > const Chris@16: operator =(expr const &a) Chris@16: { Chris@16: proto::expr< Chris@16: proto::tag::assign Chris@16: , list2 Chris@16: , 2 Chris@16: > that = {*this, a}; Chris@16: return that; Chris@16: } Chris@16: Chris@16: /// Assignment Chris@16: /// Chris@16: /// \param a The rhs. Chris@16: /// \return A new \c expr\<\> node representing an assignment of \c a to \c *this. Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: proto::expr< Chris@16: proto::tag::assign Chris@16: , list2::type> Chris@16: , 2 Chris@16: > const Chris@16: operator =(A &a) const Chris@16: { Chris@16: proto::expr< Chris@16: proto::tag::assign Chris@16: , list2::type> Chris@16: , 2 Chris@16: > that = {*this, proto::as_child(a)}; Chris@16: return that; Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: proto::expr< Chris@16: proto::tag::assign Chris@16: , list2::type> Chris@16: , 2 Chris@16: > const Chris@16: operator =(A const &a) const Chris@16: { Chris@16: proto::expr< Chris@16: proto::tag::assign Chris@16: , list2::type> Chris@16: , 2 Chris@16: > that = {*this, proto::as_child(a)}; Chris@16: return that; Chris@16: } Chris@16: Chris@16: #ifdef BOOST_PROTO_DEFINE_TERMINAL Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: proto::expr< Chris@16: proto::tag::assign Chris@16: , list2::type> Chris@16: , 2 Chris@16: > const Chris@16: operator =(A &a) Chris@16: { Chris@16: proto::expr< Chris@16: proto::tag::assign Chris@16: , list2::type> Chris@16: , 2 Chris@16: > that = {*this, proto::as_child(a)}; Chris@16: return that; Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: proto::expr< Chris@16: proto::tag::assign Chris@16: , list2::type> Chris@16: , 2 Chris@16: > const Chris@16: operator =(A const &a) Chris@16: { Chris@16: proto::expr< Chris@16: proto::tag::assign Chris@16: , list2::type> Chris@16: , 2 Chris@16: > that = {*this, proto::as_child(a)}; Chris@16: return that; Chris@16: } Chris@16: #endif Chris@16: Chris@16: /// Subscript Chris@16: /// Chris@16: /// \param a The rhs. Chris@16: /// \return A new \c expr\<\> node representing \c *this subscripted with \c a. Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: proto::expr< Chris@16: proto::tag::subscript Chris@16: , list2::type> Chris@16: , 2 Chris@16: > const Chris@16: operator [](A &a) const Chris@16: { Chris@16: proto::expr< Chris@16: proto::tag::subscript Chris@16: , list2::type> Chris@16: , 2 Chris@16: > that = {*this, proto::as_child(a)}; Chris@16: return that; Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: proto::expr< Chris@16: proto::tag::subscript Chris@16: , list2::type> Chris@16: , 2 Chris@16: > const Chris@16: operator [](A const &a) const Chris@16: { Chris@16: proto::expr< Chris@16: proto::tag::subscript Chris@16: , list2::type> Chris@16: , 2 Chris@16: > that = {*this, proto::as_child(a)}; Chris@16: return that; Chris@16: } Chris@16: Chris@16: #ifdef BOOST_PROTO_DEFINE_TERMINAL Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: proto::expr< Chris@16: proto::tag::subscript Chris@16: , list2::type> Chris@16: , 2 Chris@16: > const Chris@16: operator [](A &a) Chris@16: { Chris@16: proto::expr< Chris@16: proto::tag::subscript Chris@16: , list2::type> Chris@16: , 2 Chris@16: > that = {*this, proto::as_child(a)}; Chris@16: return that; Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: proto::expr< Chris@16: proto::tag::subscript Chris@16: , list2::type> Chris@16: , 2 Chris@16: > const Chris@16: operator [](A const &a) Chris@16: { Chris@16: proto::expr< Chris@16: proto::tag::subscript Chris@16: , list2::type> Chris@16: , 2 Chris@16: > that = {*this, proto::as_child(a)}; Chris@16: return that; Chris@16: } Chris@16: #endif Chris@16: Chris@16: /// Encodes the return type of \c expr\<\>::operator(), for use with \c boost::result_of\<\> Chris@16: /// Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename result_of::funop::type const type; Chris@16: }; Chris@16: Chris@16: #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::funop< Chris@16: expr const(A const &...) Chris@16: , expr Chris@16: , default_domain Chris@16: >::type const Chris@16: operator ()(A const &... a) const Chris@16: { Chris@16: return result_of::funop< Chris@16: expr const(A const &...) Chris@16: , expr Chris@16: , default_domain Chris@16: >::call(*this, a...); Chris@16: } Chris@16: Chris@16: #ifdef BOOST_PROTO_DEFINE_TERMINAL Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::funop< Chris@16: expr(A const &...) Chris@16: , expr Chris@16: , default_domain Chris@16: >::type const Chris@16: operator ()(A const &... a) Chris@16: { Chris@16: return result_of::funop< Chris@16: expr(A const &...) Chris@16: , expr Chris@16: , default_domain Chris@16: >::call(*this, a...); Chris@16: } Chris@16: #endif Chris@16: Chris@16: #else // BOOST_NO_CXX11_VARIADIC_TEMPLATES Chris@16: Chris@16: /// Function call Chris@16: /// Chris@16: /// \return A new \c expr\<\> node representing the function invocation of \c (*this)(). Chris@16: BOOST_FORCEINLINE Chris@16: proto::expr, 1> const Chris@16: operator ()() const Chris@16: { Chris@16: proto::expr, 1> that = {*this}; Chris@16: return that; Chris@16: } Chris@16: Chris@16: #ifdef BOOST_PROTO_DEFINE_TERMINAL Chris@16: /// \overload Chris@16: /// Chris@16: BOOST_FORCEINLINE Chris@16: proto::expr, 1> const Chris@16: operator ()() Chris@16: { Chris@16: proto::expr, 1> that = {*this}; Chris@16: return that; Chris@16: } Chris@16: #endif Chris@16: Chris@16: #define BOOST_PP_ITERATION_PARAMS_2 \ Chris@16: (3, (1, BOOST_PP_DEC(BOOST_PROTO_MAX_FUNCTION_CALL_ARITY), )) Chris@16: #include BOOST_PP_ITERATE() Chris@16: Chris@16: #endif Chris@16: }; Chris@16: Chris@16: #undef ARG_COUNT Chris@16: Chris@16: #endif