Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: /// \file traits.hpp Chris@16: /// Contains definitions for child\<\>, child_c\<\>, left\<\>, Chris@16: /// right\<\>, tag_of\<\>, and the helper functions child(), child_c(), Chris@16: /// value(), left() and right(). 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: #ifndef BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005 Chris@16: #define BOOST_PROTO_ARG_TRAITS_HPP_EAN_04_01_2005 Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@101: #if defined(_MSC_VER) Chris@16: # pragma warning(push) Chris@16: # if BOOST_WORKAROUND( BOOST_MSVC, >= 1400 ) Chris@16: # pragma warning(disable: 4180) // warning C4180: qualifier applied to function type has no meaning; ignored Chris@16: # endif Chris@16: # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined Chris@16: #endif Chris@16: Chris@16: namespace boost { namespace proto Chris@16: { Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct if_vararg Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct if_vararg Chris@16: : T Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_callable2_ Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_callable2_ Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template::value)> Chris@16: struct is_callable_ Chris@16: : is_callable2_ Chris@16: {}; Chris@16: Chris@16: } Chris@16: Chris@16: /// \brief Boolean metafunction which detects whether a type is Chris@16: /// a callable function object type or not. Chris@16: /// Chris@16: /// is_callable\<\> is used by the when\<\> transform Chris@16: /// to determine whether a function type R(A1,A2,...AN) is a Chris@16: /// callable transform or an object transform. (The former are evaluated Chris@16: /// using call\<\> and the later with make\<\>.) If Chris@16: /// is_callable\::value is \c true, the function type is Chris@16: /// a callable transform; otherwise, it is an object transform. Chris@16: /// Chris@16: /// Unless specialized for a type \c T, is_callable\::value Chris@16: /// is computed as follows: Chris@16: /// Chris@16: /// \li If \c T is a template type X\, where all \c Yx Chris@16: /// are types for \c x in [0,N], is_callable\::value Chris@16: /// is is_same\::value. Chris@16: /// \li If \c T has a nested type \c proto_is_callable_ that is a typedef Chris@16: /// for \c void, is_callable\::value is \c true. (Note: this is Chris@16: /// the case for any type that derives from \c proto::callable.) Chris@16: /// \li Otherwise, is_callable\::value is \c false. Chris@16: template Chris@16: struct is_callable Chris@16: : proto::detail::is_callable_ Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template<> Chris@16: struct is_callable Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template<> Chris@16: struct is_callable Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template Chris@16: struct is_callable > Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: #if BOOST_WORKAROUND(__GNUC__, == 3) || (BOOST_WORKAROUND(__GNUC__, == 4) && __GNUC_MINOR__ == 0) Chris@16: // work around GCC bug Chris@16: template Chris@16: struct is_callable > Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: // work around GCC bug Chris@16: template Chris@16: struct is_callable > Chris@16: : mpl::false_ Chris@16: {}; Chris@16: #endif Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct is_transform_ Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_transform_ Chris@16: : mpl::true_ Chris@16: {}; Chris@16: } Chris@16: Chris@16: /// \brief Boolean metafunction which detects whether a type is Chris@16: /// a PrimitiveTransform type or not. Chris@16: /// Chris@16: /// is_transform\<\> is used by the call\<\> transform Chris@16: /// to determine whether the function types R(), R(A1), Chris@16: /// and R(A1, A2) should be passed the expression, state and data Chris@16: /// parameters (as needed). Chris@16: /// Chris@16: /// Unless specialized for a type \c T, is_transform\::value Chris@16: /// is computed as follows: Chris@16: /// Chris@16: /// \li If \c T has a nested type \c proto_is_transform_ that is a typedef Chris@16: /// for \c void, is_transform\::value is \c true. (Note: this is Chris@16: /// the case for any type that derives from an instantiation of \c proto::transform.) Chris@16: /// \li Otherwise, is_transform\::value is \c false. Chris@16: template Chris@16: struct is_transform Chris@16: : proto::detail::is_transform_ Chris@16: {}; Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct is_aggregate_ Chris@16: : is_pod Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_aggregate_, void> Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_aggregate_, void> Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_aggregate_ Chris@16: : mpl::true_ Chris@16: {}; Chris@16: } Chris@16: Chris@16: /// \brief A Boolean metafunction that indicates whether a type requires Chris@16: /// aggregate initialization. Chris@16: /// Chris@16: /// is_aggregate\<\> is used by the make\<\> transform Chris@16: /// to determine how to construct an object of some type \c T, given some Chris@16: /// initialization arguments a0,a1,...aN. Chris@16: /// If is_aggregate\::value is \c true, then an object of Chris@16: /// type T will be initialized as T t = {a0,a1,...aN};. Otherwise, Chris@16: /// it will be initialized as T t(a0,a1,...aN). Chris@16: template Chris@16: struct is_aggregate Chris@16: : proto::detail::is_aggregate_ Chris@16: {}; Chris@16: Chris@16: /// \brief A Boolean metafunction that indicates whether a given Chris@16: /// type \c T is a Proto expression type. Chris@16: /// Chris@16: /// If \c T has a nested type \c proto_is_expr_ that is a typedef Chris@16: /// for \c void, is_expr\::value is \c true. (Note, this Chris@16: /// is the case for proto::expr\<\>, any type that is derived Chris@16: /// from proto::extends\<\> or that uses the Chris@16: /// BOOST_PROTO_BASIC_EXTENDS() macro.) Otherwise, Chris@16: /// is_expr\::value is \c false. Chris@16: template Chris@16: struct is_expr Chris@16: : mpl::false_ Chris@16: {}; Chris@16: Chris@16: /// \brief A Boolean metafunction that indicates whether a given Chris@16: /// type \c T is a Proto expression type. Chris@16: /// Chris@16: /// If \c T has a nested type \c proto_is_expr_ that is a typedef Chris@16: /// for \c void, is_expr\::value is \c true. (Note, this Chris@16: /// is the case for proto::expr\<\>, any type that is derived Chris@16: /// from proto::extends\<\> or that uses the Chris@16: /// BOOST_PROTO_BASIC_EXTENDS() macro.) Otherwise, Chris@16: /// is_expr\::value is \c false. Chris@16: template Chris@16: struct is_expr Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct is_expr Chris@16: : is_expr Chris@16: {}; Chris@16: Chris@16: /// \brief A metafunction that returns the tag type of a Chris@16: /// Proto expression. Chris@16: template Chris@16: struct tag_of Chris@16: { Chris@16: typedef typename Expr::proto_tag type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct tag_of Chris@16: { Chris@16: typedef typename Expr::proto_tag type; Chris@16: }; Chris@16: Chris@16: /// \brief A metafunction that returns the arity of a Chris@16: /// Proto expression. Chris@16: template Chris@16: struct arity_of Chris@16: : Expr::proto_arity Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct arity_of Chris@16: : Expr::proto_arity Chris@16: {}; Chris@16: Chris@16: namespace result_of Chris@16: { Chris@16: /// \brief A metafunction that computes the return type of the \c as_expr() Chris@16: /// function. Chris@16: template Chris@16: struct as_expr Chris@16: { Chris@16: typedef typename Domain::template as_expr::result_type type; Chris@16: }; Chris@16: Chris@16: /// \brief A metafunction that computes the return type of the \c as_child() Chris@16: /// function. Chris@16: template Chris@16: struct as_child Chris@16: { Chris@16: typedef typename Domain::template as_child::result_type type; Chris@16: }; Chris@16: Chris@16: /// \brief A metafunction that returns the type of the Nth child Chris@16: /// of a Proto expression, where N is an MPL Integral Constant. Chris@16: /// Chris@16: /// result_of::child\ is equivalent to Chris@16: /// result_of::child_c\. Chris@16: template*/> Chris@16: struct child Chris@16: : child_c Chris@16: {}; Chris@16: Chris@16: /// \brief A metafunction that returns the type of the value Chris@16: /// of a terminal Proto expression. Chris@16: /// Chris@16: template Chris@16: struct value Chris@16: { Chris@16: /// Verify that we are actually operating on a terminal Chris@16: BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c); Chris@16: Chris@16: /// The raw type of the Nth child as it is stored within Chris@16: /// \c Expr. This may be a value or a reference Chris@16: typedef typename Expr::proto_child0 value_type; Chris@16: Chris@16: /// The "value" type of the child, suitable for storage by value, Chris@16: /// computed as follows: Chris@16: /// \li T const(&)[N] becomes T[N] Chris@16: /// \li T[N] becomes T[N] Chris@16: /// \li T(&)[N] becomes T[N] Chris@16: /// \li R(&)(A0,...) becomes R(&)(A0,...) Chris@16: /// \li T const & becomes T Chris@16: /// \li T & becomes T Chris@16: /// \li T becomes T Chris@16: typedef typename detail::term_traits::value_type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct value Chris@16: { Chris@16: /// Verify that we are actually operating on a terminal Chris@16: BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c); Chris@16: Chris@16: /// The raw type of the Nth child as it is stored within Chris@16: /// \c Expr. This may be a value or a reference Chris@16: typedef typename Expr::proto_child0 value_type; Chris@16: Chris@16: /// The "reference" type of the child, suitable for storage by Chris@16: /// reference, computed as follows: Chris@16: /// \li T const(&)[N] becomes T const(&)[N] Chris@16: /// \li T[N] becomes T(&)[N] Chris@16: /// \li T(&)[N] becomes T(&)[N] Chris@16: /// \li R(&)(A0,...) becomes R(&)(A0,...) Chris@16: /// \li T const & becomes T const & Chris@16: /// \li T & becomes T & Chris@16: /// \li T becomes T & Chris@16: typedef typename detail::term_traits::reference type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct value Chris@16: { Chris@16: /// Verify that we are actually operating on a terminal Chris@16: BOOST_STATIC_ASSERT(0 == Expr::proto_arity_c); Chris@16: Chris@16: /// The raw type of the Nth child as it is stored within Chris@16: /// \c Expr. This may be a value or a reference Chris@16: typedef typename Expr::proto_child0 value_type; Chris@16: Chris@16: /// The "const reference" type of the child, suitable for storage by Chris@16: /// const reference, computed as follows: Chris@16: /// \li T const(&)[N] becomes T const(&)[N] Chris@16: /// \li T[N] becomes T const(&)[N] Chris@16: /// \li T(&)[N] becomes T(&)[N] Chris@16: /// \li R(&)(A0,...) becomes R(&)(A0,...) Chris@16: /// \li T const & becomes T const & Chris@16: /// \li T & becomes T & Chris@16: /// \li T becomes T const & Chris@16: typedef typename detail::term_traits::const_reference type; Chris@16: }; Chris@16: Chris@16: /// \brief A metafunction that returns the type of the left child Chris@16: /// of a binary Proto expression. Chris@16: /// Chris@16: /// result_of::left\ is equivalent to Chris@16: /// result_of::child_c\. Chris@16: template Chris@16: struct left Chris@16: : child_c Chris@16: {}; Chris@16: Chris@16: /// \brief A metafunction that returns the type of the right child Chris@16: /// of a binary Proto expression. Chris@16: /// Chris@16: /// result_of::right\ is equivalent to Chris@16: /// result_of::child_c\. Chris@16: template Chris@16: struct right Chris@16: : child_c Chris@16: {}; Chris@16: Chris@16: } // namespace result_of Chris@16: Chris@16: /// \brief A metafunction for generating terminal expression types, Chris@16: /// a grammar element for matching terminal expressions, and a Chris@16: /// PrimitiveTransform that returns the current expression unchanged. Chris@16: template Chris@16: struct terminal Chris@16: : proto::transform, int> Chris@16: { Chris@16: typedef proto::expr, 0> type; Chris@16: typedef proto::basic_expr, 0> proto_grammar; Chris@16: Chris@16: template Chris@16: struct impl : transform_impl Chris@16: { Chris@16: typedef Expr result_type; Chris@16: Chris@16: /// \param e The current expression Chris@16: /// \pre matches\ \>::value is \c true. Chris@16: /// \return \c e Chris@16: /// \throw nothrow Chris@16: BOOST_FORCEINLINE Chris@16: BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param) Chris@16: operator ()( Chris@16: typename impl::expr_param e Chris@16: , typename impl::state_param Chris@16: , typename impl::data_param Chris@16: ) const Chris@16: { Chris@16: return e; Chris@16: } Chris@16: }; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: typedef proto::tag::terminal proto_tag; Chris@16: /// INTERNAL ONLY Chris@16: typedef T proto_child0; Chris@16: }; Chris@16: Chris@16: /// \brief A metafunction for generating ternary conditional expression types, Chris@16: /// a grammar element for matching ternary conditional expressions, and a Chris@16: /// PrimitiveTransform that dispatches to the pass_through\<\> Chris@16: /// transform. Chris@16: template Chris@16: struct if_else_ Chris@16: : proto::transform, int> Chris@16: { Chris@16: typedef proto::expr, 3> type; Chris@16: typedef proto::basic_expr, 3> proto_grammar; Chris@16: Chris@16: template Chris@16: struct impl Chris@16: : detail::pass_through_impl Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: typedef proto::tag::if_else_ proto_tag; Chris@16: /// INTERNAL ONLY Chris@16: typedef T proto_child0; Chris@16: /// INTERNAL ONLY Chris@16: typedef U proto_child1; Chris@16: /// INTERNAL ONLY Chris@16: typedef V proto_child2; Chris@16: }; Chris@16: Chris@16: /// \brief A metafunction for generating nullary expression types with a Chris@16: /// specified tag type, Chris@16: /// a grammar element for matching nullary expressions, and a Chris@16: /// PrimitiveTransform that returns the current expression unchanged. Chris@16: /// Chris@16: /// Use nullary_expr\<_, _\> as a grammar element to match any Chris@16: /// nullary expression. Chris@16: template Chris@16: struct nullary_expr Chris@16: : proto::transform, int> Chris@16: { Chris@16: typedef proto::expr, 0> type; Chris@16: typedef proto::basic_expr, 0> proto_grammar; Chris@16: Chris@16: template Chris@16: struct impl : transform_impl Chris@16: { Chris@16: typedef Expr result_type; Chris@16: Chris@16: /// \param e The current expression Chris@16: /// \pre matches\ \>::value is \c true. Chris@16: /// \return \c e Chris@16: /// \throw nothrow Chris@16: BOOST_FORCEINLINE Chris@16: BOOST_PROTO_RETURN_TYPE_STRICT_LOOSE(result_type, typename impl::expr_param) Chris@16: operator ()( Chris@16: typename impl::expr_param e Chris@16: , typename impl::state_param Chris@16: , typename impl::data_param Chris@16: ) const Chris@16: { Chris@16: return e; Chris@16: } Chris@16: }; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: typedef Tag proto_tag; Chris@16: /// INTERNAL ONLY Chris@16: typedef T proto_child0; Chris@16: }; Chris@16: Chris@16: /// \brief A metafunction for generating unary expression types with a Chris@16: /// specified tag type, Chris@16: /// a grammar element for matching unary expressions, and a Chris@16: /// PrimitiveTransform that dispatches to the pass_through\<\> Chris@16: /// transform. Chris@16: /// Chris@16: /// Use unary_expr\<_, _\> as a grammar element to match any Chris@16: /// unary expression. Chris@16: template Chris@16: struct unary_expr Chris@16: : proto::transform, int> Chris@16: { Chris@16: typedef proto::expr, 1> type; Chris@16: typedef proto::basic_expr, 1> proto_grammar; Chris@16: Chris@16: template Chris@16: struct impl Chris@16: : detail::pass_through_impl Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: typedef Tag proto_tag; Chris@16: /// INTERNAL ONLY Chris@16: typedef T proto_child0; Chris@16: }; Chris@16: Chris@16: /// \brief A metafunction for generating binary expression types with a Chris@16: /// specified tag type, Chris@16: /// a grammar element for matching binary expressions, and a Chris@16: /// PrimitiveTransform that dispatches to the pass_through\<\> Chris@16: /// transform. Chris@16: /// Chris@16: /// Use binary_expr\<_, _, _\> as a grammar element to match any Chris@16: /// binary expression. Chris@16: template Chris@16: struct binary_expr Chris@16: : proto::transform, int> Chris@16: { Chris@16: typedef proto::expr, 2> type; Chris@16: typedef proto::basic_expr, 2> proto_grammar; Chris@16: Chris@16: template Chris@16: struct impl Chris@16: : detail::pass_through_impl Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: typedef Tag proto_tag; Chris@16: /// INTERNAL ONLY Chris@16: typedef T proto_child0; Chris@16: /// INTERNAL ONLY Chris@16: typedef U proto_child1; Chris@16: }; Chris@16: Chris@16: #define BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(Op) \ Chris@16: template \ Chris@16: struct Op \ Chris@16: : proto::transform, int> \ Chris@16: { \ Chris@16: typedef proto::expr, 1> type; \ Chris@16: typedef proto::basic_expr, 1> proto_grammar; \ Chris@16: \ Chris@16: template \ Chris@16: struct impl \ Chris@16: : detail::pass_through_impl \ Chris@16: {}; \ Chris@16: \ Chris@16: typedef proto::tag::Op proto_tag; \ Chris@16: typedef T proto_child0; \ Chris@16: }; \ Chris@16: /**/ Chris@16: Chris@16: #define BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(Op) \ Chris@16: template \ Chris@16: struct Op \ Chris@16: : proto::transform, int> \ Chris@16: { \ Chris@16: typedef proto::expr, 2> type; \ Chris@16: typedef proto::basic_expr, 2> proto_grammar; \ Chris@16: \ Chris@16: template \ Chris@16: struct impl \ Chris@16: : detail::pass_through_impl \ Chris@16: {}; \ Chris@16: \ Chris@16: typedef proto::tag::Op proto_tag; \ Chris@16: typedef T proto_child0; \ Chris@16: typedef U proto_child1; \ Chris@16: }; \ Chris@16: /**/ Chris@16: Chris@16: BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(unary_plus) Chris@16: BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(negate) Chris@16: BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(dereference) Chris@16: BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(complement) Chris@16: BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(address_of) Chris@16: BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(logical_not) Chris@16: BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(pre_inc) Chris@16: BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(pre_dec) Chris@16: BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(post_inc) Chris@16: BOOST_PROTO_DEFINE_UNARY_METAFUNCTION(post_dec) Chris@16: Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_left) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_right) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(multiplies) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(divides) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(modulus) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(plus) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(minus) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(less) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(greater) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(less_equal) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(greater_equal) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(equal_to) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(not_equal_to) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(logical_or) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(logical_and) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_or) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_and) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_xor) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(comma) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(mem_ptr) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(assign) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_left_assign) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(shift_right_assign) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(multiplies_assign) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(divides_assign) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(modulus_assign) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(plus_assign) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(minus_assign) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_or_assign) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_and_assign) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(bitwise_xor_assign) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(subscript) Chris@16: BOOST_PROTO_DEFINE_BINARY_METAFUNCTION(member) Chris@16: Chris@16: #undef BOOST_PROTO_DEFINE_UNARY_METAFUNCTION Chris@16: #undef BOOST_PROTO_DEFINE_BINARY_METAFUNCTION Chris@16: Chris@16: #include Chris@16: Chris@16: namespace functional Chris@16: { Chris@16: /// \brief A callable PolymorphicFunctionObject that is Chris@16: /// equivalent to the \c as_expr() function. Chris@16: template Chris@16: struct as_expr Chris@16: { Chris@16: BOOST_PROTO_CALLABLE() Chris@16: Chris@16: template Chris@16: struct result; Chris@16: Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename Domain::template as_expr::result_type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename Domain::template as_expr::result_type type; Chris@16: }; Chris@16: Chris@16: /// \brief Wrap an object in a Proto terminal if it isn't a Chris@16: /// Proto expression already. Chris@16: /// \param t The object to wrap. Chris@16: /// \return proto::as_expr\(t) Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: operator ()(T &t) const Chris@16: { Chris@16: return typename Domain::template as_expr()(t); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: operator ()(T const &t) const Chris@16: { Chris@16: return typename Domain::template as_expr()(t); Chris@16: } Chris@16: Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, == 1310) Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: operator ()(T (&t)[N_]) const Chris@16: { Chris@16: return typename Domain::template as_expr()(t); Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: operator ()(T const (&t)[N_]) const Chris@16: { Chris@16: return typename Domain::template as_expr()(t); Chris@16: } Chris@16: #endif Chris@16: }; Chris@16: Chris@16: /// \brief A callable PolymorphicFunctionObject that is Chris@16: /// equivalent to the \c as_child() function. Chris@16: template Chris@16: struct as_child Chris@16: { Chris@16: BOOST_PROTO_CALLABLE() Chris@16: Chris@16: template Chris@16: struct result; Chris@16: Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename Domain::template as_child::result_type type; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename Domain::template as_child::result_type type; Chris@16: }; Chris@16: Chris@16: /// \brief Wrap an object in a Proto terminal if it isn't a Chris@16: /// Proto expression already. Chris@16: /// \param t The object to wrap. Chris@16: /// \return proto::as_child\(t) Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: operator ()(T &t) const Chris@16: { Chris@16: return typename Domain::template as_child()(t); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: operator ()(T const &t) const Chris@16: { Chris@16: return typename Domain::template as_child()(t); Chris@16: } Chris@16: }; Chris@16: Chris@16: /// \brief A callable PolymorphicFunctionObject that is Chris@16: /// equivalent to the \c child_c() function. Chris@16: template Chris@16: struct child_c Chris@16: { Chris@16: BOOST_PROTO_CALLABLE() Chris@16: Chris@16: template Chris@16: struct result; Chris@16: Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename result_of::child_c::type type; Chris@16: }; Chris@16: Chris@16: /// \brief Return the Nth child of the given expression. Chris@16: /// \param expr The expression node. Chris@16: /// \pre is_expr\::value is \c true Chris@16: /// \pre N \< Expr::proto_arity::value Chris@16: /// \return proto::child_c\(expr) Chris@16: /// \throw nothrow Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::child_c::type Chris@16: operator ()(Expr &e) const Chris@16: { Chris@16: return result_of::child_c::call(e); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::child_c::type Chris@16: operator ()(Expr const &e) const Chris@16: { Chris@16: return result_of::child_c::call(e); Chris@16: } Chris@16: }; Chris@16: Chris@16: /// \brief A callable PolymorphicFunctionObject that is Chris@16: /// equivalent to the \c child() function. Chris@16: /// Chris@16: /// A callable PolymorphicFunctionObject that is Chris@16: /// equivalent to the \c child() function. \c N is required Chris@16: /// to be an MPL Integral Constant. Chris@16: template*/> Chris@16: struct child Chris@16: { Chris@16: BOOST_PROTO_CALLABLE() Chris@16: Chris@16: template Chris@16: struct result; Chris@16: Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename result_of::child::type type; Chris@16: }; Chris@16: Chris@16: /// \brief Return the Nth child of the given expression. Chris@16: /// \param expr The expression node. Chris@16: /// \pre is_expr\::value is \c true Chris@16: /// \pre N::value \< Expr::proto_arity::value Chris@16: /// \return proto::child\(expr) Chris@16: /// \throw nothrow Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::child::type Chris@16: operator ()(Expr &e) const Chris@16: { Chris@16: return result_of::child::call(e); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::child::type Chris@16: operator ()(Expr const &e) const Chris@16: { Chris@16: return result_of::child::call(e); Chris@16: } Chris@16: }; Chris@16: Chris@16: /// \brief A callable PolymorphicFunctionObject that is Chris@16: /// equivalent to the \c value() function. Chris@16: struct value Chris@16: { Chris@16: BOOST_PROTO_CALLABLE() Chris@16: Chris@16: template Chris@16: struct result; Chris@16: Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename result_of::value::type type; Chris@16: }; Chris@16: Chris@16: /// \brief Return the value of the given terminal expression. Chris@16: /// \param expr The terminal expression node. Chris@16: /// \pre is_expr\::value is \c true Chris@16: /// \pre 0 == Expr::proto_arity::value Chris@16: /// \return proto::value(expr) Chris@16: /// \throw nothrow Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::value::type Chris@16: operator ()(Expr &e) const Chris@16: { Chris@16: return e.proto_base().child0; Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::value::type Chris@16: operator ()(Expr const &e) const Chris@16: { Chris@16: return e.proto_base().child0; Chris@16: } Chris@16: }; Chris@16: Chris@16: /// \brief A callable PolymorphicFunctionObject that is Chris@16: /// equivalent to the \c left() function. Chris@16: struct left Chris@16: { Chris@16: BOOST_PROTO_CALLABLE() Chris@16: Chris@16: template Chris@16: struct result; Chris@16: Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename result_of::left::type type; Chris@16: }; Chris@16: Chris@16: /// \brief Return the left child of the given binary expression. Chris@16: /// \param expr The expression node. Chris@16: /// \pre is_expr\::value is \c true Chris@16: /// \pre 2 == Expr::proto_arity::value Chris@16: /// \return proto::left(expr) Chris@16: /// \throw nothrow Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::left::type Chris@16: operator ()(Expr &e) const Chris@16: { Chris@16: return e.proto_base().child0; Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::left::type Chris@16: operator ()(Expr const &e) const Chris@16: { Chris@16: return e.proto_base().child0; Chris@16: } Chris@16: }; Chris@16: Chris@16: /// \brief A callable PolymorphicFunctionObject that is Chris@16: /// equivalent to the \c right() function. Chris@16: struct right Chris@16: { Chris@16: BOOST_PROTO_CALLABLE() Chris@16: Chris@16: template Chris@16: struct result; Chris@16: Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef typename result_of::right::type type; Chris@16: }; Chris@16: Chris@16: /// \brief Return the right child of the given binary expression. Chris@16: /// \param expr The expression node. Chris@16: /// \pre is_expr\::value is \c true Chris@16: /// \pre 2 == Expr::proto_arity::value Chris@16: /// \return proto::right(expr) Chris@16: /// \throw nothrow Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::right::type Chris@16: operator ()(Expr &e) const Chris@16: { Chris@16: return e.proto_base().child1; Chris@16: } Chris@16: Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::right::type Chris@16: operator ()(Expr const &e) const Chris@16: { Chris@16: return e.proto_base().child1; Chris@16: } Chris@16: }; Chris@16: Chris@16: } Chris@16: Chris@16: /// \brief A function that wraps non-Proto expression types in Proto Chris@16: /// terminals and leaves Proto expression types alone. Chris@16: /// Chris@16: /// The as_expr() function turns objects into Proto terminals if Chris@16: /// they are not Proto expression types already. Non-Proto types are Chris@16: /// held by value, if possible. Types which are already Proto types are Chris@16: /// left alone and returned by reference. Chris@16: /// Chris@16: /// This function can be called either with an explicitly specified Chris@16: /// \c Domain parameter (i.e., as_expr\(t)), or Chris@16: /// without (i.e., as_expr(t)). If no domain is Chris@16: /// specified, \c default_domain is assumed. Chris@16: /// Chris@16: /// If is_expr\::value is \c true, then the argument is Chris@16: /// returned unmodified, by reference. Otherwise, the argument is wrapped Chris@16: /// in a Proto terminal expression node according to the following rules. Chris@16: /// If \c T is a function type, let \c A be T &. Otherwise, let Chris@16: /// \c A be the type \c T stripped of cv-qualifiers. Then, \c as_expr() Chris@16: /// returns Domain()(terminal\::type::make(t)). Chris@16: /// Chris@16: /// \param t The object to wrap. Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)) Chris@16: { Chris@16: return default_domain::as_expr()(t); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: as_expr(T const &t) Chris@16: { Chris@16: return default_domain::as_expr()(t); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: as_expr(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)) Chris@16: { Chris@16: return typename Domain::template as_expr()(t); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: as_expr(T const &t) Chris@16: { Chris@16: return typename Domain::template as_expr()(t); Chris@16: } Chris@16: Chris@16: /// \brief A function that wraps non-Proto expression types in Proto Chris@16: /// terminals (by reference) and returns Proto expression types by Chris@16: /// reference Chris@16: /// Chris@16: /// The as_child() function turns objects into Proto terminals if Chris@16: /// they are not Proto expression types already. Non-Proto types are Chris@16: /// held by reference. Types which are already Proto types are simply Chris@16: /// returned as-is. Chris@16: /// Chris@16: /// This function can be called either with an explicitly specified Chris@16: /// \c Domain parameter (i.e., as_child\(t)), or Chris@16: /// without (i.e., as_child(t)). If no domain is Chris@16: /// specified, \c default_domain is assumed. Chris@16: /// Chris@16: /// If is_expr\::value is \c true, then the argument is Chris@16: /// returned as-is. Otherwise, \c as_child() returns Chris@16: /// Domain()(terminal\::type::make(t)). Chris@16: /// Chris@16: /// \param t The object to wrap. Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: as_child(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)) Chris@16: { Chris@16: return default_domain::as_child()(t); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: as_child(T const &t) Chris@16: { Chris@16: return default_domain::as_child()(t); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: as_child(T &t BOOST_PROTO_DISABLE_IF_IS_CONST(T) BOOST_PROTO_DISABLE_IF_IS_FUNCTION(T)) Chris@16: { Chris@16: return typename Domain::template as_child()(t); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename add_const::type>::type Chris@16: as_child(T const &t) Chris@16: { Chris@16: return typename Domain::template as_child()(t); Chris@16: } Chris@16: Chris@16: /// \brief Return the Nth child of the specified Proto expression. Chris@16: /// Chris@16: /// Return the Nth child of the specified Proto expression. If Chris@16: /// \c N is not specified, as in \c child(expr), then \c N is assumed Chris@16: /// to be mpl::long_\<0\>. The child is returned by Chris@16: /// reference. Chris@16: /// Chris@16: /// \param expr The Proto expression. Chris@16: /// \pre is_expr\::value is \c true. Chris@16: /// \pre \c N is an MPL Integral Constant. Chris@16: /// \pre N::value \< Expr::proto_arity::value Chris@16: /// \throw nothrow Chris@16: /// \return A reference to the Nth child Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::child::type Chris@16: child(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) Chris@16: { Chris@16: return result_of::child::call(e); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::child::type Chris@16: child(Expr const &e) Chris@16: { Chris@16: return result_of::child::call(e); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename detail::expr_traits::reference Chris@16: child(Expr2 &expr2 BOOST_PROTO_DISABLE_IF_IS_CONST(Expr2)) Chris@16: { Chris@16: return expr2.proto_base().child0; Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename detail::expr_traits::const_reference Chris@16: child(Expr2 const &expr2) Chris@16: { Chris@16: return expr2.proto_base().child0; Chris@16: } Chris@16: Chris@16: /// \brief Return the Nth child of the specified Proto expression. Chris@16: /// Chris@16: /// Return the Nth child of the specified Proto expression. The child Chris@16: /// is returned by reference. Chris@16: /// Chris@16: /// \param expr The Proto expression. Chris@16: /// \pre is_expr\::value is \c true. Chris@16: /// \pre N \< Expr::proto_arity::value Chris@16: /// \throw nothrow Chris@16: /// \return A reference to the Nth child Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::child_c::type Chris@16: child_c(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) Chris@16: { Chris@16: return result_of::child_c::call(e); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::child_c::type Chris@16: child_c(Expr const &e) Chris@16: { Chris@16: return result_of::child_c::call(e); Chris@16: } Chris@16: Chris@16: /// \brief Return the value stored within the specified Proto Chris@16: /// terminal expression. Chris@16: /// Chris@16: /// Return the value stored within the specified Proto Chris@16: /// terminal expression. The value is returned by Chris@16: /// reference. Chris@16: /// Chris@16: /// \param expr The Proto terminal expression. Chris@16: /// \pre N::value == 0 Chris@16: /// \throw nothrow Chris@16: /// \return A reference to the terminal's value Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::value::type Chris@16: value(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) Chris@16: { Chris@16: return e.proto_base().child0; Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::value::type Chris@16: value(Expr const &e) Chris@16: { Chris@16: return e.proto_base().child0; Chris@16: } Chris@16: Chris@16: /// \brief Return the left child of the specified binary Proto Chris@16: /// expression. Chris@16: /// Chris@16: /// Return the left child of the specified binary Proto expression. The Chris@16: /// child is returned by reference. Chris@16: /// Chris@16: /// \param expr The Proto expression. Chris@16: /// \pre is_expr\::value is \c true. Chris@16: /// \pre 2 == Expr::proto_arity::value Chris@16: /// \throw nothrow Chris@16: /// \return A reference to the left child Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::left::type Chris@16: left(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) Chris@16: { Chris@16: return e.proto_base().child0; Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::left::type Chris@16: left(Expr const &e) Chris@16: { Chris@16: return e.proto_base().child0; Chris@16: } Chris@16: Chris@16: /// \brief Return the right child of the specified binary Proto Chris@16: /// expression. Chris@16: /// Chris@16: /// Return the right child of the specified binary Proto expression. The Chris@16: /// child is returned by reference. Chris@16: /// Chris@16: /// \param expr The Proto expression. Chris@16: /// \pre is_expr\::value is \c true. Chris@16: /// \pre 2 == Expr::proto_arity::value Chris@16: /// \throw nothrow Chris@16: /// \return A reference to the right child Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::right::type Chris@16: right(Expr &e BOOST_PROTO_DISABLE_IF_IS_CONST(Expr)) Chris@16: { Chris@16: return e.proto_base().child1; Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::right::type Chris@16: right(Expr const &e) Chris@16: { Chris@16: return e.proto_base().child1; Chris@16: } Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template Chris@16: struct is_callable > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template Chris@16: struct is_callable > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template Chris@16: struct is_callable > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template Chris@16: struct is_callable > Chris@16: : mpl::true_ Chris@16: {}; Chris@16: Chris@16: }} Chris@16: Chris@101: #if defined(_MSC_VER) Chris@16: # pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: #endif