Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: /// \file make_expr.hpp Chris@16: /// Definition of the \c make_expr() and \c unpack_expr() utilities for Chris@16: /// building Proto expression nodes from child nodes or from a Fusion Chris@16: /// sequence of child nodes, respectively. 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_MAKE_EXPR_HPP_EAN_04_01_2005 Chris@16: #define BOOST_PROTO_MAKE_EXPR_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: #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: # pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored 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: /// INTERNAL ONLY Chris@16: /// Chris@16: #define BOOST_PROTO_AS_CHILD_TYPE(Z, N, DATA) \ Chris@16: typename boost::proto::detail::protoify< \ Chris@16: BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 0, DATA), N) \ Chris@16: , BOOST_PP_TUPLE_ELEM(3, 2, DATA) \ Chris@16: >::result_type \ Chris@16: /**/ Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: #define BOOST_PROTO_AS_CHILD(Z, N, DATA) \ Chris@16: boost::proto::detail::protoify< \ Chris@16: BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 0, DATA), N) \ Chris@16: , BOOST_PP_TUPLE_ELEM(3, 2, DATA) \ Chris@16: >()(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 1, DATA), N)) \ Chris@16: /**/ Chris@16: Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct protoify Chris@16: : Domain::template as_expr Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct protoify Chris@16: : Domain::template as_child Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct protoify, Domain> Chris@16: : Domain::template as_child Chris@16: {}; Chris@16: Chris@16: template Chris@16: struct protoify const, Domain> Chris@16: : Domain::template as_child Chris@16: {}; Chris@16: Chris@16: // Definition of detail::unpack_expr_ Chris@16: #include Chris@16: Chris@16: // Definition of detail::make_expr_ Chris@16: #include Chris@16: } Chris@16: Chris@16: namespace result_of Chris@16: { Chris@16: /// \brief Metafunction that computes the return type of the Chris@16: /// \c make_expr() function, with a domain deduced from the Chris@16: /// domains of the children. Chris@16: /// Chris@16: /// Use the result_of::make_expr\<\> metafunction to Chris@16: /// compute the return type of the \c make_expr() function. Chris@16: /// Chris@16: /// In this specialization, the domain is deduced from the Chris@16: /// domains of the child types. (If Chris@16: /// is_domain\::value is \c true, then another Chris@16: /// specialization is selected.) Chris@16: template< Chris@16: typename Tag Chris@16: , BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_ARITY, typename A) Chris@16: , typename Void1 // = void Chris@16: , typename Void2 // = void Chris@16: > Chris@16: struct make_expr Chris@16: { Chris@16: /// Same as result_of::make_expr\::type Chris@16: /// where \c D is the deduced domain, which is calculated as follows: Chris@16: /// Chris@16: /// For each \c x in [0,N) (proceeding in order beginning with Chris@16: /// x=0), if domain_of\::type is not Chris@16: /// \c default_domain, then \c D is domain_of\::type. Chris@16: /// Otherwise, \c D is \c default_domain. Chris@16: typedef Chris@16: typename detail::make_expr_< Chris@16: Tag Chris@16: , deduce_domain Chris@16: BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A) Chris@16: >::result_type Chris@16: type; Chris@16: }; Chris@16: Chris@16: /// \brief Metafunction that computes the return type of the Chris@16: /// \c make_expr() function, within the specified domain. Chris@16: /// Chris@16: /// Use the result_of::make_expr\<\> metafunction to compute Chris@16: /// the return type of the \c make_expr() function. Chris@16: template< Chris@16: typename Tag Chris@16: , typename Domain Chris@16: BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, typename A) Chris@16: > Chris@16: struct make_expr< Chris@16: Tag Chris@16: , Domain Chris@16: BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A) Chris@16: , typename Domain::proto_is_domain_ Chris@16: > Chris@16: { Chris@16: /// If \c Tag is tag::terminal, then \c type is a Chris@16: /// typedef for boost::result_of\ \>)\>::type. Chris@16: /// Chris@16: /// Otherwise, \c type is a typedef for boost::result_of\::type, ... as_child\::type\>) Chris@16: /// \>::type, where \c N is the number of non-void template Chris@16: /// arguments, and as_child\::type is evaluated as Chris@16: /// follows: Chris@16: /// Chris@16: /// \li If is_expr\::value is \c true, then the Chris@16: /// child type is \c A. Chris@16: /// \li If \c A is B & or cv boost::reference_wrapper\, Chris@16: /// and is_expr\::value is \c true, then the Chris@16: /// child type is B &. Chris@16: /// \li If is_expr\::value is \c false, then the Chris@16: /// child type is boost::result_of\ \> Chris@16: /// )\>::type. Chris@16: /// \li If \c A is B & or cv boost::reference_wrapper\, Chris@16: /// and is_expr\::value is \c false, then the Chris@16: /// child type is boost::result_of\ \> Chris@16: /// )\>::type. Chris@16: typedef Chris@16: typename detail::make_expr_< Chris@16: Tag Chris@16: , Domain Chris@16: BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A) Chris@16: >::result_type Chris@16: type; Chris@16: }; Chris@16: Chris@16: /// \brief Metafunction that computes the return type of the Chris@16: /// \c unpack_expr() function, with a domain deduced from the Chris@16: /// domains of the children. Chris@16: /// Chris@16: /// Use the result_of::unpack_expr\<\> metafunction to Chris@16: /// compute the return type of the \c unpack_expr() function. Chris@16: /// Chris@16: /// \c Sequence is a Fusion Forward Sequence. Chris@16: /// Chris@16: /// In this specialization, the domain is deduced from the Chris@16: /// domains of the child types. (If Chris@16: /// is_domain\::value is \c true, then another Chris@16: /// specialization is selected.) Chris@16: template< Chris@16: typename Tag Chris@16: , typename Sequence Chris@16: , typename Void1 // = void Chris@16: , typename Void2 // = void Chris@16: > Chris@16: struct unpack_expr Chris@16: { Chris@16: /// Let \c S be the type of a Fusion Random Access Sequence Chris@16: /// equivalent to \c Sequence. Then \c type is the Chris@16: /// same as result_of::make_expr\::type, ... Chris@16: /// fusion::result_of::value_at_c\::type\>::type, Chris@16: /// where \c N is the size of \c S. Chris@16: typedef Chris@16: typename detail::unpack_expr_< Chris@16: Tag Chris@16: , deduce_domain Chris@16: , Sequence Chris@16: , fusion::result_of::size::type::value Chris@16: >::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: /// \brief Metafunction that computes the return type of the Chris@16: /// \c unpack_expr() function, within the specified domain. Chris@16: /// Chris@16: /// Use the result_of::make_expr\<\> metafunction to compute Chris@16: /// the return type of the \c make_expr() function. Chris@16: template Chris@16: struct unpack_expr Chris@16: { Chris@16: /// Let \c S be the type of a Fusion Random Access Sequence Chris@16: /// equivalent to \c Sequence. Then \c type is the Chris@16: /// same as result_of::make_expr\::type, ... Chris@16: /// fusion::result_of::value_at_c\::type\>::type, Chris@16: /// where \c N is the size of \c S. Chris@16: typedef Chris@16: typename detail::unpack_expr_< Chris@16: Tag Chris@16: , Domain Chris@16: , Sequence Chris@16: , fusion::result_of::size::type::value Chris@16: >::type Chris@16: type; Chris@16: }; Chris@16: } Chris@16: Chris@16: namespace functional Chris@16: { Chris@16: /// \brief A callable function object equivalent to the Chris@16: /// \c proto::make_expr() function. Chris@16: /// Chris@16: /// In all cases, functional::make_expr\()(a0, ... aN) Chris@16: /// is equivalent to proto::make_expr\(a0, ... aN). Chris@16: /// Chris@16: /// functional::make_expr\()(a0, ... aN) Chris@16: /// is equivalent to proto::make_expr\(a0, ... aN). Chris@16: template Chris@16: struct make_expr Chris@16: { Chris@16: BOOST_PROTO_CALLABLE() Chris@16: BOOST_PROTO_POLY_FUNCTION() Chris@16: Chris@16: template Chris@16: struct result; Chris@16: Chris@16: template Chris@16: struct result Chris@16: { Chris@16: typedef Chris@16: typename result_of::make_expr< Chris@16: Tag Chris@16: , Domain Chris@16: , A0 Chris@16: >::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: /// Construct an expression node with tag type \c Tag Chris@16: /// and in the domain \c Domain. Chris@16: /// Chris@16: /// \return proto::make_expr\(a0,...aN) Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::make_expr< Chris@16: Tag Chris@16: , Domain Chris@16: , A0 const Chris@16: >::type const Chris@16: operator ()(A0 const &a0) const Chris@16: { Chris@16: return proto::detail::make_expr_< Chris@16: Tag Chris@16: , Domain Chris@16: , A0 const Chris@16: >()(a0); Chris@16: } Chris@16: Chris@16: // Additional overloads generated by the preprocessor ... Chris@16: #include Chris@16: Chris@16: /// INTERNAL ONLY Chris@16: /// Chris@16: template< Chris@16: BOOST_PP_ENUM_BINARY_PARAMS( Chris@16: BOOST_PROTO_MAX_ARITY Chris@16: , typename A Chris@16: , = void BOOST_PP_INTERCEPT Chris@16: ) Chris@16: > Chris@16: struct impl Chris@16: : detail::make_expr_< Chris@16: Tag Chris@16: , Domain Chris@16: BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, A) Chris@16: > Chris@16: {}; Chris@16: }; Chris@16: Chris@16: /// \brief A callable function object equivalent to the Chris@16: /// \c proto::unpack_expr() function. Chris@16: /// Chris@16: /// In all cases, functional::unpack_expr\()(seq) Chris@16: /// is equivalent to proto::unpack_expr\(seq). Chris@16: /// Chris@16: /// functional::unpack_expr\()(seq) Chris@16: /// is equivalent to proto::unpack_expr\(seq). Chris@16: template Chris@16: struct unpack_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 Chris@16: typename result_of::unpack_expr< Chris@16: Tag Chris@16: , Domain Chris@16: , typename remove_reference::type Chris@16: >::type Chris@16: type; Chris@16: }; Chris@16: Chris@16: /// Construct an expression node with tag type \c Tag Chris@16: /// and in the domain \c Domain. Chris@16: /// Chris@16: /// \param sequence A Fusion Forward Sequence Chris@16: /// \return proto::unpack_expr\(sequence) Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::unpack_expr::type const Chris@16: operator ()(Sequence const &sequence) const Chris@16: { Chris@16: return proto::detail::unpack_expr_< Chris@16: Tag Chris@16: , Domain Chris@16: , Sequence const Chris@16: , fusion::result_of::size::type::value Chris@16: >::call(sequence); Chris@16: } Chris@16: }; Chris@16: Chris@16: } // namespace functional Chris@16: Chris@16: /// \brief Construct an expression of the requested tag type Chris@16: /// with a domain and with the specified arguments as children. Chris@16: /// Chris@16: /// This function template may be invoked either with or without Chris@16: /// specifying a \c Domain argument. If no domain is specified, Chris@16: /// the domain is deduced by examining in order the domains of Chris@16: /// the given arguments and taking the first that is not Chris@16: /// \c default_domain, if any such domain exists, or Chris@16: /// \c default_domain otherwise. Chris@16: /// Chris@16: /// Let \c wrap_(x) be defined such that: Chris@16: /// \li If \c x is a boost::reference_wrapper\<\>, Chris@16: /// \c wrap_(x) is equivalent to as_child\(x.get()). Chris@16: /// \li Otherwise, \c wrap_(x) is equivalent to Chris@16: /// as_expr\(x). Chris@16: /// Chris@16: /// Let make_\(b0,...bN) be defined as Chris@16: /// expr\ \>::make(c0,...cN) Chris@16: /// where \c Bx is the type of \c bx. Chris@16: /// Chris@16: /// \return Domain()(make_\(wrap_(a0),...wrap_(aN))). Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename lazy_disable_if< Chris@16: is_domain Chris@16: , result_of::make_expr< Chris@16: Tag Chris@16: , A0 const Chris@16: > Chris@16: >::type const Chris@16: make_expr(A0 const &a0) Chris@16: { Chris@16: return proto::detail::make_expr_< Chris@16: Tag Chris@16: , deduce_domain Chris@16: , A0 const Chris@16: >()(a0); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::make_expr< Chris@16: Tag Chris@16: , Domain Chris@16: , C0 const Chris@16: >::type const Chris@16: make_expr(C0 const &c0) Chris@16: { Chris@16: return proto::detail::make_expr_< Chris@16: Tag Chris@16: , Domain Chris@16: , C0 const Chris@16: >()(c0); Chris@16: } Chris@16: Chris@16: // Additional overloads generated by the preprocessor... Chris@16: #include Chris@16: Chris@16: /// \brief Construct an expression of the requested tag type Chris@16: /// with a domain and with childres from the specified Fusion Chris@16: /// Forward Sequence. Chris@16: /// Chris@16: /// This function template may be invoked either with or without Chris@16: /// specifying a \c Domain argument. If no domain is specified, Chris@16: /// the domain is deduced by examining in order the domains of the Chris@16: /// elements of \c sequence and taking the first that is not Chris@16: /// \c default_domain, if any such domain exists, or Chris@16: /// \c default_domain otherwise. Chris@16: /// Chris@16: /// Let \c s be a Fusion Random Access Sequence equivalent to \c sequence. Chris@16: /// Let wrap_\(s), where \c s has type \c S, be defined Chris@16: /// such that: Chris@16: /// \li If fusion::result_of::value_at_c\::type is a reference, Chris@16: /// wrap_\(s) is equivalent to Chris@16: /// as_child\(fusion::at_c\(s)). Chris@16: /// \li Otherwise, wrap_\(s) is equivalent to Chris@16: /// as_expr\(fusion::at_c\(s)). Chris@16: /// Chris@16: /// Let make_\(b0,...bN) be defined as Chris@16: /// expr\ \>::make(b0,...bN) Chris@16: /// where \c Bx is the type of \c bx. Chris@16: /// Chris@16: /// \param sequence a Fusion Forward Sequence. Chris@16: /// \return Domain()(make_\(wrap_\<0\>(s),...wrap_\(s))), Chris@16: /// where N is the size of \c Sequence. Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename lazy_disable_if< Chris@16: is_domain Chris@16: , result_of::unpack_expr Chris@16: >::type const Chris@16: unpack_expr(Sequence const &sequence) Chris@16: { Chris@16: return proto::detail::unpack_expr_< Chris@16: Tag Chris@16: , deduce_domain Chris@16: , Sequence const Chris@16: , fusion::result_of::size::type::value Chris@16: >::call(sequence); Chris@16: } Chris@16: Chris@16: /// \overload Chris@16: /// Chris@16: template Chris@16: BOOST_FORCEINLINE Chris@16: typename result_of::unpack_expr::type const Chris@16: unpack_expr(Sequence2 const &sequence2) Chris@16: { Chris@16: return proto::detail::unpack_expr_< Chris@16: Tag Chris@16: , Domain Chris@16: , Sequence2 const Chris@16: , fusion::result_of::size::type::value Chris@16: >::call(sequence2); 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 // BOOST_PROTO_MAKE_EXPR_HPP_EAN_04_01_2005