/////////////////////////////////////////////////////////////////////////////// /// \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 #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma warning(push) # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined #endif namespace boost { namespace proto { namespace detail { template struct is_applyable : mpl::and_, is_transform > {}; template::value> struct nested_type { typedef typename T::type type; }; template struct nested_type { typedef T type; }; template struct nested_type_if { typedef T type; static bool const applied = false; }; template struct nested_type_if : nested_type { static bool const applied = true; }; template< typename R , typename Expr, typename State, typename Data BOOST_PROTO_TEMPLATE_ARITY_PARAM(long Arity = detail::template_arity::value) > struct make_ { typedef R type; static bool const applied = false; }; template< typename R , typename Expr, typename State, typename Data , bool IsApplyable = is_applyable::value > struct make_if_ : make_ {}; template struct make_if_ : uncvref::template impl::result_type> { static bool const applied = true; }; #if BOOST_WORKAROUND(__GNUC__, == 3) || (BOOST_WORKAROUND(__GNUC__, == 4) && __GNUC_MINOR__ == 0) // work around GCC bug template struct make_if_, Expr, State, Data, false> { typedef proto::expr type; static bool const applied = false; }; // work around GCC bug template struct make_if_, Expr, State, Data, false> { typedef proto::basic_expr type; static bool const applied = false; }; #endif template::value> struct construct_ { typedef Type result_type; BOOST_FORCEINLINE Type operator ()() const { return Type(); } // Other overloads generated by the preprocessor #include }; template struct construct_ { typedef Type result_type; BOOST_FORCEINLINE Type operator ()() const { return Type(); } // Other overloads generated by the preprocessor #include }; } /// \brief A PrimitiveTransform which prevents another PrimitiveTransform /// from being applied in an \c ObjectTransform. /// /// When building higher order transforms with make\<\> or /// lazy\<\>, you sometimes would like to build types that /// are parameterized with Proto transforms. In such lambda-style /// transforms, Proto will unhelpfully find all nested transforms /// and apply them, even if you don't want them to be applied. Consider /// the following transform, which will replace the \c _ in /// Bar<_>() with proto::terminal\::type: /// /// \code /// template /// struct Bar /// {}; /// /// struct Foo /// : proto::when<_, Bar<_>() > /// {}; /// /// proto::terminal::type i = {0}; /// /// int main() /// { /// Foo()(i); /// std::cout << typeid(Foo()(i)).name() << std::endl; /// } /// \endcode /// /// If you actually wanted to default-construct an object of type /// Bar\<_\>, you would have to protect the \c _ to prevent /// it from being applied. You can use proto::protect\<\> /// as follows: /// /// \code /// // OK: replace anything with Bar<_>() /// struct Foo /// : proto::when<_, Bar >() > /// {}; /// \endcode template struct protect : transform > { template struct impl { typedef PrimitiveTransform result_type; }; }; /// \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 /// /// boost::result_of\ \>(Expr, State, Data)\>::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 boost::result_of\ \>(Expr, State, Data)\>::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 /// boost::result_of\(Expr, State, Data)\>::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 : transform > { template struct impl : transform_impl { typedef typename detail::make_if_::type result_type; /// \return result_type() BOOST_FORCEINLINE result_type operator ()( typename impl::expr_param , typename impl::state_param , typename impl::data_param ) const { return result_type(); } }; }; /// INTERNAL ONLY template struct make > : make {}; // Other specializations generated by the preprocessor. #include #include /// INTERNAL ONLY /// template struct is_callable > : mpl::true_ {}; /// INTERNAL ONLY /// template struct is_callable > : mpl::true_ {}; }} #if defined(_MSC_VER) && (_MSC_VER >= 1020) # pragma warning(pop) #endif #endif