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