| #ifndef BOOST_PP_IS_ITERATING |
| /////////////////////////////////////////////////////////////////////////////// |
| /// \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/version.hpp> |
| #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/proto/proto_fwd.hpp> |
| #include <boost/proto/fusion.hpp> |
| #include <boost/proto/traits.hpp> |
| #include <boost/proto/transform/call.hpp> |
| #include <boost/proto/transform/impl.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; |
| |
| #if BOOST_VERSION >= 104200 |
| |
| 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_); |
| } |
| |
| #else |
| |
| template<typename This, typename Expr, typename State> |
| struct result<This(Expr, State)> |
| { |
| typedef |
| typename when<_, Transform>::template impl<Expr, State, Data>::result_type |
| type; |
| }; |
| |
| template<typename Expr, typename State> |
| typename when<_, Transform>::template impl<Expr &, State const &, Data>::result_type |
| operator ()(Expr &e, State const &s) const |
| { |
| return typename when<_, Transform>::template impl<Expr &, State const &, Data>()(e, s, this->d_); |
| } |
| |
| #endif |
| |
| 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 |
| {}; |
| |
| #define BOOST_PROTO_CHILD_N_TYPE(N)\ |
| BOOST_PP_CAT(proto_child, N)\ |
| /**/ |
| |
| #define BOOST_PROTO_FOLD_STATE_TYPE(Z, N, DATA) \ |
| typedef \ |
| typename when<_, Fun>::template impl< \ |
| typename result_of::child_c<Expr, N>::type \ |
| , BOOST_PP_CAT(state, N) \ |
| , Data \ |
| >::result_type \ |
| BOOST_PP_CAT(state, BOOST_PP_INC(N)); \ |
| /**/ |
| |
| #define BOOST_PROTO_FOLD_STATE(Z, N, DATA) \ |
| BOOST_PP_CAT(state, BOOST_PP_INC(N)) \ |
| BOOST_PP_CAT(s, BOOST_PP_INC(N)) \ |
| = typename when<_, Fun>::template impl< \ |
| typename result_of::child_c<Expr, N>::type \ |
| , BOOST_PP_CAT(state, N) \ |
| , Data \ |
| >()( \ |
| proto::child_c<N>(e) \ |
| , BOOST_PP_CAT(s, N) \ |
| , d \ |
| ); \ |
| /**/ |
| |
| #define BOOST_PROTO_REVERSE_FOLD_STATE_TYPE(Z, N, DATA) \ |
| typedef \ |
| typename when<_, Fun>::template impl< \ |
| typename result_of::child_c< \ |
| Expr \ |
| , BOOST_PP_SUB(DATA, BOOST_PP_INC(N)) \ |
| >::type \ |
| , BOOST_PP_CAT(state, BOOST_PP_SUB(DATA, N)) \ |
| , Data \ |
| >::result_type \ |
| BOOST_PP_CAT(state, BOOST_PP_SUB(DATA, BOOST_PP_INC(N))); \ |
| /**/ |
| |
| #define BOOST_PROTO_REVERSE_FOLD_STATE(Z, N, DATA) \ |
| BOOST_PP_CAT(state, BOOST_PP_SUB(DATA, BOOST_PP_INC(N))) \ |
| BOOST_PP_CAT(s, BOOST_PP_SUB(DATA, BOOST_PP_INC(N))) \ |
| = typename when<_, Fun>::template impl< \ |
| typename result_of::child_c< \ |
| Expr \ |
| , BOOST_PP_SUB(DATA, BOOST_PP_INC(N)) \ |
| >::type \ |
| , BOOST_PP_CAT(state, BOOST_PP_SUB(DATA, N)) \ |
| , Data \ |
| >()( \ |
| proto::child_c<BOOST_PP_SUB(DATA, BOOST_PP_INC(N))>(e) \ |
| , BOOST_PP_CAT(s, BOOST_PP_SUB(DATA, N)) \ |
| , d \ |
| ); \ |
| /**/ |
| |
| #define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PROTO_MAX_ARITY, <boost/proto/transform/fold.hpp>)) |
| #include BOOST_PP_ITERATE() |
| |
| #undef BOOST_PROTO_REVERSE_FOLD_STATE |
| #undef BOOST_PROTO_REVERSE_FOLD_STATE_TYPE |
| #undef BOOST_PROTO_FOLD_STATE |
| #undef BOOST_PROTO_FOLD_STATE_TYPE |
| #undef BOOST_PROTO_CHILD_N_TYPE |
| |
| } // 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. It uses |
| /// the \c _reverse callable PolymorphicFunctionObject |
| /// to create a <tt>fusion::reverse_view\<\></tt> of the |
| /// sequence before invoking <tt>fusion::fold\<\></tt>. |
| template<typename Sequence, typename State0, typename Fun> |
| struct reverse_fold |
| : fold<call<_reverse(Sequence)>, State0, Fun> |
| {}; |
| |
| // 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 |
| |
| #else |
| |
| #define N BOOST_PP_ITERATION() |
| |
| template<typename State0, typename Fun, typename Expr, typename State, typename Data> |
| struct fold_impl<State0, Fun, Expr, State, Data, N> |
| : transform_impl<Expr, State, Data> |
| { |
| typedef typename when<_, State0>::template impl<Expr, State, Data>::result_type state0; |
| BOOST_PP_REPEAT(N, BOOST_PROTO_FOLD_STATE_TYPE, N) |
| typedef BOOST_PP_CAT(state, N) result_type; |
| |
| result_type operator ()( |
| typename fold_impl::expr_param e |
| , typename fold_impl::state_param s |
| , typename fold_impl::data_param d |
| ) const |
| { |
| state0 s0 = |
| typename when<_, State0>::template impl<Expr, State, Data>()(e, s, d); |
| BOOST_PP_REPEAT(N, BOOST_PROTO_FOLD_STATE, N) |
| return BOOST_PP_CAT(s, N); |
| } |
| }; |
| |
| template<typename State0, typename Fun, typename Expr, typename State, typename Data> |
| struct reverse_fold_impl<State0, Fun, Expr, State, Data, N> |
| : transform_impl<Expr, State, Data> |
| { |
| typedef typename when<_, State0>::template impl<Expr, State, Data>::result_type BOOST_PP_CAT(state, N); |
| BOOST_PP_REPEAT(N, BOOST_PROTO_REVERSE_FOLD_STATE_TYPE, N) |
| typedef state0 result_type; |
| |
| result_type operator ()( |
| typename reverse_fold_impl::expr_param e |
| , typename reverse_fold_impl::state_param s |
| , typename reverse_fold_impl::data_param d |
| ) const |
| { |
| BOOST_PP_CAT(state, N) BOOST_PP_CAT(s, N) = |
| typename when<_, State0>::template impl<Expr, State, Data>()(e, s, d); |
| BOOST_PP_REPEAT(N, BOOST_PROTO_REVERSE_FOLD_STATE, N) |
| return s0; |
| } |
| }; |
| |
| #undef N |
| |
| #endif |