285 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			285 lines
		
	
	
		
			9.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								///////////////////////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								/// \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 <boost/detail/workaround.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/preprocessor/repetition/enum.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/preprocessor/repetition/enum_params.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/preprocessor/repetition/enum_binary_params.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/preprocessor/repetition/repeat_from_to.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/preprocessor/facilities/intercept.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/preprocessor/cat.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/preprocessor/iteration/iterate.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/preprocessor/selection/max.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/preprocessor/arithmetic/inc.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/and.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/mpl/aux_/has_type.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/proto/detail/template_arity.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/utility/result_of.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/proto/proto_fwd.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/proto/traits.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/proto/args.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/proto/transform/impl.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/proto/transform/detail/pack.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/proto/detail/as_lvalue.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/proto/detail/ignore_unused.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(_MSC_VER)
							 | 
						||
| 
								 | 
							
								# pragma warning(push)
							 | 
						||
| 
								 | 
							
								# pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace boost { namespace proto
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    namespace detail
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        template<typename T>
							 | 
						||
| 
								 | 
							
								        struct is_applyable
							 | 
						||
| 
								 | 
							
								          : mpl::and_<is_callable<T>, is_transform<T> >
							 | 
						||
| 
								 | 
							
								        {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<typename T, bool HasType = mpl::aux::has_type<T>::value>
							 | 
						||
| 
								 | 
							
								        struct nested_type
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            typedef typename T::type type;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<typename T>
							 | 
						||
| 
								 | 
							
								        struct nested_type<T, false>
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            typedef T type;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<typename T, bool Applied>
							 | 
						||
| 
								 | 
							
								        struct nested_type_if
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            typedef T type;
							 | 
						||
| 
								 | 
							
								            static bool const applied = false;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<typename T>
							 | 
						||
| 
								 | 
							
								        struct nested_type_if<T, true>
							 | 
						||
| 
								 | 
							
								          : nested_type<T>
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            static bool const applied = true;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<
							 | 
						||
| 
								 | 
							
								            typename R
							 | 
						||
| 
								 | 
							
								          , typename Expr, typename State, typename Data
							 | 
						||
| 
								 | 
							
								            BOOST_PROTO_TEMPLATE_ARITY_PARAM(long Arity = detail::template_arity<R>::value)
							 | 
						||
| 
								 | 
							
								        >
							 | 
						||
| 
								 | 
							
								        struct make_
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            typedef R type;
							 | 
						||
| 
								 | 
							
								            static bool const applied = false;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<
							 | 
						||
| 
								 | 
							
								            typename R
							 | 
						||
| 
								 | 
							
								          , typename Expr, typename State, typename Data
							 | 
						||
| 
								 | 
							
								          , bool IsApplyable = is_applyable<R>::value
							 | 
						||
| 
								 | 
							
								        >
							 | 
						||
| 
								 | 
							
								        struct make_if_
							 | 
						||
| 
								 | 
							
								          : make_<R, Expr, State, Data>
							 | 
						||
| 
								 | 
							
								        {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<typename R, typename Expr, typename State, typename Data>
							 | 
						||
| 
								 | 
							
								        struct make_if_<R, Expr, State, Data, true>
							 | 
						||
| 
								 | 
							
								          : uncvref<typename when<_, R>::template impl<Expr, State, Data>::result_type>
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            static bool const applied = true;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        #if BOOST_WORKAROUND(__GNUC__, == 3) || (BOOST_WORKAROUND(__GNUC__, == 4) && __GNUC_MINOR__ == 0)
							 | 
						||
| 
								 | 
							
								        // work around GCC bug
							 | 
						||
| 
								 | 
							
								        template<typename Tag, typename Args, long N, typename Expr, typename State, typename Data>
							 | 
						||
| 
								 | 
							
								        struct make_if_<proto::expr<Tag, Args, N>, Expr, State, Data, false>
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            typedef proto::expr<Tag, Args, N> type;
							 | 
						||
| 
								 | 
							
								            static bool const applied = false;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // work around GCC bug
							 | 
						||
| 
								 | 
							
								        template<typename Tag, typename Args, long N, typename Expr, typename State, typename Data>
							 | 
						||
| 
								 | 
							
								        struct make_if_<proto::basic_expr<Tag, Args, N>, Expr, State, Data, false>
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            typedef proto::basic_expr<Tag, Args, N> type;
							 | 
						||
| 
								 | 
							
								            static bool const applied = false;
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								        #endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<typename Type, bool IsAggregate = detail::is_aggregate_<Type>::value>
							 | 
						||
| 
								 | 
							
								        struct construct_
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            typedef Type result_type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            BOOST_FORCEINLINE
							 | 
						||
| 
								 | 
							
								            Type operator ()() const
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                return Type();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // Other overloads generated by the preprocessor
							 | 
						||
| 
								 | 
							
								            #include <boost/proto/transform/detail/construct_funop.hpp>
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        template<typename Type>
							 | 
						||
| 
								 | 
							
								        struct construct_<Type, true>
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            typedef Type result_type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            BOOST_FORCEINLINE
							 | 
						||
| 
								 | 
							
								            Type operator ()() const
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                return Type();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // Other overloads generated by the preprocessor
							 | 
						||
| 
								 | 
							
								            #include <boost/proto/transform/detail/construct_pod_funop.hpp>
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// \brief A PrimitiveTransform which prevents another PrimitiveTransform
							 | 
						||
| 
								 | 
							
								    /// from being applied in an \c ObjectTransform.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// When building higher order transforms with <tt>make\<\></tt> or
							 | 
						||
| 
								 | 
							
								    /// <tt>lazy\<\></tt>, 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
							 | 
						||
| 
								 | 
							
								    /// <tt>Bar<_>()</tt> with <tt>proto::terminal\<int\>::type</tt>:
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \code
							 | 
						||
| 
								 | 
							
								    /// template<typename T>
							 | 
						||
| 
								 | 
							
								    /// struct Bar
							 | 
						||
| 
								 | 
							
								    /// {};
							 | 
						||
| 
								 | 
							
								    /// 
							 | 
						||
| 
								 | 
							
								    /// struct Foo
							 | 
						||
| 
								 | 
							
								    ///   : proto::when<_, Bar<_>() >
							 | 
						||
| 
								 | 
							
								    /// {};
							 | 
						||
| 
								 | 
							
								    /// 
							 | 
						||
| 
								 | 
							
								    /// proto::terminal<int>::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
							 | 
						||
| 
								 | 
							
								    /// <tt>Bar\<_\></tt>, you would have to protect the \c _ to prevent
							 | 
						||
| 
								 | 
							
								    /// it from being applied. You can use <tt>proto::protect\<\></tt>
							 | 
						||
| 
								 | 
							
								    /// as follows:
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \code
							 | 
						||
| 
								 | 
							
								    /// // OK: replace anything with Bar<_>()
							 | 
						||
| 
								 | 
							
								    /// struct Foo
							 | 
						||
| 
								 | 
							
								    ///   : proto::when<_, Bar<protect<_> >() >
							 | 
						||
| 
								 | 
							
								    /// {};
							 | 
						||
| 
								 | 
							
								    /// \endcode
							 | 
						||
| 
								 | 
							
								    template<typename PrimitiveTransform>
							 | 
						||
| 
								 | 
							
								    struct protect : transform<protect<PrimitiveTransform> >
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        template<typename, typename, typename>
							 | 
						||
| 
								 | 
							
								        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 <tt>make\<\></tt> 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 <tt>proto::is_callable\< type \>::value</tt> is \c true
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// <tt>boost::result_of\<make\<T\<X0,X1,...\> \>(Expr, State, Data)\>::type</tt>
							 | 
						||
| 
								 | 
							
								    /// is evaluated as follows. For each \c X in <tt>X0,X1,...</tt>, do:
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// \li If \c X is a template like <tt>U\<Y0,Y1,...\></tt>, then let <tt>X'</tt>
							 | 
						||
| 
								 | 
							
								    ///     be <tt>boost::result_of\<make\<U\<Y0,Y1,...\> \>(Expr, State, Data)\>::type</tt>
							 | 
						||
| 
								 | 
							
								    ///     (which evaluates this procedure recursively). Note whether any
							 | 
						||
| 
								 | 
							
								    ///     substitutions took place during this operation.
							 | 
						||
| 
								 | 
							
								    /// \li Otherwise, if \c X is a transform, then let <tt>X'</tt> be
							 | 
						||
| 
								 | 
							
								    ///     <tt>boost::result_of\<when\<_, X\>(Expr, State, Data)\>::type</tt>.
							 | 
						||
| 
								 | 
							
								    ///     Note that a substitution took place.
							 | 
						||
| 
								 | 
							
								    /// \li Otherwise, let <tt>X'</tt> be \c X, and note that no substitution
							 | 
						||
| 
								 | 
							
								    ///     took place.
							 | 
						||
| 
								 | 
							
								    /// \li If any substitutions took place in any of the above steps and
							 | 
						||
| 
								 | 
							
								    ///     <tt>T\<X0',X1',...\></tt> has a nested <tt>::type</tt> typedef,
							 | 
						||
| 
								 | 
							
								    ///     the result type is <tt>T\<X0',X1',...\>::type</tt>.
							 | 
						||
| 
								 | 
							
								    /// \li Otherwise, the result type is <tt>T\<X0',X1',...\></tt>.
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    /// Note that <tt>when\<\></tt> is implemented in terms of <tt>call\<\></tt>
							 | 
						||
| 
								 | 
							
								    /// and <tt>make\<\></tt>, so the above procedure is evaluated recursively.
							 | 
						||
| 
								 | 
							
								    template<typename Object>
							 | 
						||
| 
								 | 
							
								    struct make : transform<make<Object> >
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        template<typename Expr, typename State, typename Data>
							 | 
						||
| 
								 | 
							
								        struct impl : transform_impl<Expr, State, Data>
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            typedef typename detail::make_if_<Object, Expr, State, Data>::type result_type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            /// \return <tt>result_type()</tt>
							 | 
						||
| 
								 | 
							
								            BOOST_FORCEINLINE
							 | 
						||
| 
								 | 
							
								            result_type operator ()(
							 | 
						||
| 
								 | 
							
								                typename impl::expr_param
							 | 
						||
| 
								 | 
							
								              , typename impl::state_param
							 | 
						||
| 
								 | 
							
								              , typename impl::data_param
							 | 
						||
| 
								 | 
							
								            ) const
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                return result_type();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        };
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// INTERNAL ONLY
							 | 
						||
| 
								 | 
							
								    template<typename Fun>
							 | 
						||
| 
								 | 
							
								    struct make<detail::msvc_fun_workaround<Fun> >
							 | 
						||
| 
								 | 
							
								      : make<Fun>
							 | 
						||
| 
								 | 
							
								    {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Other specializations generated by the preprocessor.
							 | 
						||
| 
								 | 
							
								    #include <boost/proto/transform/detail/make.hpp>
							 | 
						||
| 
								 | 
							
								    #include <boost/proto/transform/detail/make_gcc_workaround.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// INTERNAL ONLY
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    template<typename Object>
							 | 
						||
| 
								 | 
							
								    struct is_callable<make<Object> >
							 | 
						||
| 
								 | 
							
								      : mpl::true_
							 | 
						||
| 
								 | 
							
								    {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /// INTERNAL ONLY
							 | 
						||
| 
								 | 
							
								    ///
							 | 
						||
| 
								 | 
							
								    template<typename PrimitiveTransform>
							 | 
						||
| 
								 | 
							
								    struct is_callable<protect<PrimitiveTransform> >
							 | 
						||
| 
								 | 
							
								      : mpl::true_
							 | 
						||
| 
								 | 
							
								    {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(_MSC_VER)
							 | 
						||
| 
								 | 
							
								# pragma warning(pop)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 |