251 lines
8.6 KiB
C++
251 lines
8.6 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
/// \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
|