251 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			251 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | /////////////////////////////////////////////////////////////////////////////// | ||
|  | /// \file fold.hpp | ||
|  | /// Contains definition of the fold<> and reverse_fold<> transforms. | ||
|  | // | ||
|  | //  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_FOLD_HPP_EAN_11_04_2007 | ||
|  | #define BOOST_PROTO_TRANSFORM_FOLD_HPP_EAN_11_04_2007 | ||
|  | 
 | ||
|  | #include <boost/preprocessor/cat.hpp> | ||
|  | #include <boost/preprocessor/iteration/iterate.hpp> | ||
|  | #include <boost/preprocessor/arithmetic/inc.hpp> | ||
|  | #include <boost/preprocessor/arithmetic/sub.hpp> | ||
|  | #include <boost/preprocessor/repetition/repeat.hpp> | ||
|  | #include <boost/fusion/include/fold.hpp> | ||
|  | #include <boost/fusion/include/reverse_fold.hpp> | ||
|  | #include <boost/proto/proto_fwd.hpp> | ||
|  | #include <boost/proto/traits.hpp> | ||
|  | #include <boost/proto/transform/impl.hpp> | ||
|  | #include <boost/proto/transform/when.hpp> | ||
|  | 
 | ||
|  | namespace boost { namespace proto | ||
|  | { | ||
|  |     namespace detail | ||
|  |     { | ||
|  |         template<typename Transform, typename Data> | ||
|  |         struct as_callable | ||
|  |         { | ||
|  |             as_callable(Data d) | ||
|  |               : d_(d) | ||
|  |             {} | ||
|  | 
 | ||
|  |             template<typename Sig> | ||
|  |             struct result; | ||
|  | 
 | ||
|  |             template<typename This, typename State, typename Expr> | ||
|  |             struct result<This(State, Expr)> | ||
|  |             { | ||
|  |                 typedef | ||
|  |                     typename when<_, Transform>::template impl<Expr, State, Data>::result_type | ||
|  |                 type; | ||
|  |             }; | ||
|  | 
 | ||
|  |             template<typename State, typename Expr> | ||
|  |             typename when<_, Transform>::template impl<Expr &, State const &, Data>::result_type | ||
|  |             operator ()(State const &s, Expr &e) const | ||
|  |             { | ||
|  |                 return typename when<_, Transform>::template impl<Expr &, State const &, Data>()(e, s, this->d_); | ||
|  |             } | ||
|  | 
 | ||
|  |         private: | ||
|  |             Data d_; | ||
|  |         }; | ||
|  | 
 | ||
|  |         template< | ||
|  |             typename State0 | ||
|  |           , typename Fun | ||
|  |           , typename Expr | ||
|  |           , typename State | ||
|  |           , typename Data | ||
|  |           , long Arity = arity_of<Expr>::value | ||
|  |         > | ||
|  |         struct fold_impl | ||
|  |         {}; | ||
|  | 
 | ||
|  |         template< | ||
|  |             typename State0 | ||
|  |           , typename Fun | ||
|  |           , typename Expr | ||
|  |           , typename State | ||
|  |           , typename Data | ||
|  |           , long Arity = arity_of<Expr>::value | ||
|  |         > | ||
|  |         struct reverse_fold_impl | ||
|  |         {}; | ||
|  | 
 | ||
|  |         #include <boost/proto/transform/detail/fold_impl.hpp> | ||
|  | 
 | ||
|  |     } // namespace detail | ||
|  | 
 | ||
|  |     /// \brief A PrimitiveTransform that invokes the <tt>fusion::fold\<\></tt> | ||
|  |     /// algorithm to accumulate | ||
|  |     template<typename Sequence, typename State0, typename Fun> | ||
|  |     struct fold : transform<fold<Sequence, State0, Fun> > | ||
|  |     { | ||
|  |         template<typename Expr, typename State, typename Data> | ||
|  |         struct impl : transform_impl<Expr, State, Data> | ||
|  |         { | ||
|  |             /// \brief A Fusion sequence. | ||
|  |             typedef | ||
|  |                 typename remove_reference< | ||
|  |                     typename when<_, Sequence>::template impl<Expr, State, Data>::result_type | ||
|  |                 >::type | ||
|  |             sequence; | ||
|  | 
 | ||
|  |             /// \brief An initial state for the fold. | ||
|  |             typedef | ||
|  |                 typename remove_reference< | ||
|  |                     typename when<_, State0>::template impl<Expr, State, Data>::result_type | ||
|  |                 >::type | ||
|  |             state0; | ||
|  | 
 | ||
|  |             /// \brief <tt>fun(d)(e,s) == when\<_,Fun\>()(e,s,d)</tt> | ||
|  |             typedef | ||
|  |                 detail::as_callable<Fun, Data> | ||
|  |             fun; | ||
|  | 
 | ||
|  |             typedef | ||
|  |                 typename fusion::result_of::fold< | ||
|  |                     sequence | ||
|  |                   , state0 | ||
|  |                   , fun | ||
|  |                 >::type | ||
|  |             result_type; | ||
|  | 
 | ||
|  |             /// Let \c seq be <tt>when\<_, Sequence\>()(e, s, d)</tt>, let | ||
|  |             /// \c state0 be <tt>when\<_, State0\>()(e, s, d)</tt>, and | ||
|  |             /// let \c fun(d) be an object such that <tt>fun(d)(e, s)</tt> | ||
|  |             /// is equivalent to <tt>when\<_, Fun\>()(e, s, d)</tt>. Then, this | ||
|  |             /// function returns <tt>fusion::fold(seq, state0, fun(d))</tt>. | ||
|  |             /// | ||
|  |             /// \param e The current expression | ||
|  |             /// \param s The current state | ||
|  |             /// \param d An arbitrary data | ||
|  |             result_type operator ()( | ||
|  |                 typename impl::expr_param   e | ||
|  |               , typename impl::state_param  s | ||
|  |               , typename impl::data_param   d | ||
|  |             ) const | ||
|  |             { | ||
|  |                 typename when<_, Sequence>::template impl<Expr, State, Data> seq; | ||
|  |                 detail::as_callable<Fun, Data> f(d); | ||
|  |                 return fusion::fold( | ||
|  |                     seq(e, s, d) | ||
|  |                   , typename when<_, State0>::template impl<Expr, State, Data>()(e, s, d) | ||
|  |                   , f | ||
|  |                 ); | ||
|  |             } | ||
|  |         }; | ||
|  |     }; | ||
|  | 
 | ||
|  |     /// \brief A PrimitiveTransform that is the same as the | ||
|  |     /// <tt>fold\<\></tt> transform, except that it folds | ||
|  |     /// back-to-front instead of front-to-back. | ||
|  |     template<typename Sequence, typename State0, typename Fun> | ||
|  |     struct reverse_fold  : transform<reverse_fold<Sequence, State0, Fun> > | ||
|  |     { | ||
|  |         template<typename Expr, typename State, typename Data> | ||
|  |         struct impl : transform_impl<Expr, State, Data> | ||
|  |         { | ||
|  |             /// \brief A Fusion sequence. | ||
|  |             typedef | ||
|  |                 typename remove_reference< | ||
|  |                     typename when<_, Sequence>::template impl<Expr, State, Data>::result_type | ||
|  |                 >::type | ||
|  |             sequence; | ||
|  | 
 | ||
|  |             /// \brief An initial state for the fold. | ||
|  |             typedef | ||
|  |                 typename remove_reference< | ||
|  |                     typename when<_, State0>::template impl<Expr, State, Data>::result_type | ||
|  |                 >::type | ||
|  |             state0; | ||
|  | 
 | ||
|  |             /// \brief <tt>fun(d)(e,s) == when\<_,Fun\>()(e,s,d)</tt> | ||
|  |             typedef | ||
|  |                 detail::as_callable<Fun, Data> | ||
|  |             fun; | ||
|  | 
 | ||
|  |             typedef | ||
|  |                 typename fusion::result_of::reverse_fold< | ||
|  |                     sequence | ||
|  |                   , state0 | ||
|  |                   , fun | ||
|  |                 >::type | ||
|  |             result_type; | ||
|  | 
 | ||
|  |             /// Let \c seq be <tt>when\<_, Sequence\>()(e, s, d)</tt>, let | ||
|  |             /// \c state0 be <tt>when\<_, State0\>()(e, s, d)</tt>, and | ||
|  |             /// let \c fun(d) be an object such that <tt>fun(d)(e, s)</tt> | ||
|  |             /// is equivalent to <tt>when\<_, Fun\>()(e, s, d)</tt>. Then, this | ||
|  |             /// function returns <tt>fusion::fold(seq, state0, fun(d))</tt>. | ||
|  |             /// | ||
|  |             /// \param e The current expression | ||
|  |             /// \param s The current state | ||
|  |             /// \param d An arbitrary data | ||
|  |             result_type operator ()( | ||
|  |                 typename impl::expr_param   e | ||
|  |               , typename impl::state_param  s | ||
|  |               , typename impl::data_param   d | ||
|  |             ) const | ||
|  |             { | ||
|  |                 typename when<_, Sequence>::template impl<Expr, State, Data> seq; | ||
|  |                 detail::as_callable<Fun, Data> f(d); | ||
|  |                 return fusion::reverse_fold( | ||
|  |                     seq(e, s, d) | ||
|  |                   , typename when<_, State0>::template impl<Expr, State, Data>()(e, s, d) | ||
|  |                   , f | ||
|  |                 ); | ||
|  |             } | ||
|  |         }; | ||
|  |     }; | ||
|  | 
 | ||
|  |     // This specialization is only for improved compile-time performance | ||
|  |     // in the commom case when the Sequence transform is \c proto::_. | ||
|  |     // | ||
|  |     /// INTERNAL ONLY | ||
|  |     /// | ||
|  |     template<typename State0, typename Fun> | ||
|  |     struct fold<_, State0, Fun> : transform<fold<_, State0, Fun> > | ||
|  |     { | ||
|  |         template<typename Expr, typename State, typename Data> | ||
|  |         struct impl | ||
|  |           : detail::fold_impl<State0, Fun, Expr, State, Data> | ||
|  |         {}; | ||
|  |     }; | ||
|  | 
 | ||
|  |     // This specialization is only for improved compile-time performance | ||
|  |     // in the commom case when the Sequence transform is \c proto::_. | ||
|  |     // | ||
|  |     /// INTERNAL ONLY | ||
|  |     /// | ||
|  |     template<typename State0, typename Fun> | ||
|  |     struct reverse_fold<_, State0, Fun> : transform<reverse_fold<_, State0, Fun> > | ||
|  |     { | ||
|  |         template<typename Expr, typename State, typename Data> | ||
|  |         struct impl | ||
|  |           : detail::reverse_fold_impl<State0, Fun, Expr, State, Data> | ||
|  |         {}; | ||
|  |     }; | ||
|  | 
 | ||
|  |     /// INTERNAL ONLY | ||
|  |     /// | ||
|  |     template<typename Sequence, typename State, typename Fun> | ||
|  |     struct is_callable<fold<Sequence, State, Fun> > | ||
|  |       : mpl::true_ | ||
|  |     {}; | ||
|  | 
 | ||
|  |     /// INTERNAL ONLY | ||
|  |     /// | ||
|  |     template<typename Sequence, typename State, typename Fun> | ||
|  |     struct is_callable<reverse_fold<Sequence, State, Fun> > | ||
|  |       : mpl::true_ | ||
|  |     {}; | ||
|  | 
 | ||
|  | }} | ||
|  | 
 | ||
|  | #endif |