Imported existing code

This commit is contained in:
Hazim Gazov
2010-04-02 02:48:44 -03:00
parent 48fbc5ae91
commit 7a86d01598
13996 changed files with 2468699 additions and 0 deletions

View File

@@ -0,0 +1,362 @@
///////////////////////////////////////////////////////////////////////////////
/// \file arg.hpp
/// Contains definition of the argN 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_ARG_HPP_EAN_11_01_2007
#define BOOST_PROTO_TRANSFORM_ARG_HPP_EAN_11_01_2007
#include <boost/proto/detail/prefix.hpp>
#include <boost/proto/proto_fwd.hpp>
#include <boost/proto/traits.hpp>
#include <boost/proto/transform/impl.hpp>
#include <boost/proto/detail/suffix.hpp>
namespace boost { namespace proto
{
/// \brief A PrimitiveTransform that returns the current expression
/// unmodified
///
/// Example:
///
/// \code
/// proto::terminal<int>::type i = {42};
/// proto::terminal<int>::type & j = proto::_expr()(i);
/// assert( boost::addressof(i) == boost::addressof(j) );
/// \endcode
struct _expr : transform<_expr>
{
template<typename Expr, typename State, typename Data>
struct impl : transform_impl<Expr, State, Data>
{
typedef Expr result_type;
/// Returns the current expression.
/// \param e The current expression.
/// \return \c e
/// \throw nothrow
#ifdef BOOST_HAS_DECLTYPE
result_type
#else
typename impl::expr_param
#endif
operator()(
typename impl::expr_param e
, typename impl::state_param
, typename impl::data_param
) const
{
return e;
}
};
};
/// \brief A PrimitiveTransform that returns the current state
/// unmodified
///
/// Example:
///
/// \code
/// proto::terminal<int>::type i = {42};
/// char ch = proto::_state()(i, 'a');
/// assert( ch == 'a' );
/// \endcode
struct _state : transform<_state>
{
template<typename Expr, typename State, typename Data>
struct impl : transform_impl<Expr, State, Data>
{
typedef State result_type;
/// Returns the current state.
/// \param s The current state.
/// \return \c s
/// \throw nothrow
#ifdef BOOST_HAS_DECLTYPE
result_type
#else
typename impl::state_param
#endif
operator ()(
typename impl::expr_param
, typename impl::state_param s
, typename impl::data_param
) const
{
return s;
}
};
};
/// \brief A PrimitiveTransform that returns the current data
/// unmodified
///
/// Example:
///
/// \code
/// proto::terminal<int>::type i = {42};
/// std::string str("hello");
/// std::string & data = proto::_data()(i, 'a', str);
/// assert( &str == &data );
/// \endcode
struct _data : transform<_data>
{
template<typename Expr, typename State, typename Data>
struct impl : transform_impl<Expr, State, Data>
{
typedef Data result_type;
/// Returns the current data.
/// \param d The current data.
/// \return \c d
/// \throw nothrow
#ifdef BOOST_HAS_DECLTYPE
result_type
#else
typename impl::data_param
#endif
operator ()(
typename impl::expr_param
, typename impl::state_param
, typename impl::data_param d
) const
{
return d;
}
};
};
/// \brief A PrimitiveTransform that returns N-th child of the current
/// expression.
///
/// Example:
///
/// \code
/// proto::terminal<int>::type i = {42};
/// proto::terminal<int>::type & j = proto::_child_c<0>()(-i);
/// assert( boost::addressof(i) == boost::addressof(j) );
/// \endcode
template<int N>
struct _child_c : transform<_child_c<N> >
{
template<typename Expr, typename State, typename Data>
struct impl : transform_impl<Expr, State, Data>
{
typedef
typename result_of::child_c<Expr, N>::type
result_type;
/// Returns the N-th child of \c e
/// \pre <tt>arity_of\<Expr\>::::value \> N</tt>
/// \param e The current expression.
/// \return <tt>proto::child_c\<N\>(e)</tt>
/// \throw nothrow
#ifdef BOOST_HAS_DECLTYPE
result_type
#else
typename result_of::child_c<typename impl::expr_param, N>::type
#endif
operator ()(
typename impl::expr_param e
, typename impl::state_param
, typename impl::data_param
) const
{
return proto::child_c<N>(e);
}
};
};
/// \brief A PrimitiveTransform that returns the value of the
/// current terminal expression.
///
/// Example:
///
/// \code
/// proto::terminal<int>::type i = {42};
/// int j = proto::_value()(i);
/// assert( 42 == j );
/// \endcode
struct _value : transform<_value>
{
template<typename Expr, typename State, typename Data>
struct impl : transform_impl<Expr, State, Data>
{
typedef
typename result_of::value<Expr>::type
result_type;
/// Returns the value of the specified terminal expression.
/// \pre <tt>arity_of\<Expr\>::::value == 0</tt>.
/// \param e The current expression.
/// \return <tt>proto::value(e)</tt>
/// \throw nothrow
#ifdef BOOST_HAS_DECLTYPE
result_type
#else
typename result_of::value<typename impl::expr_param>::type
#endif
operator ()(
typename impl::expr_param e
, typename impl::state_param
, typename impl::data_param
) const
{
return proto::value(e);
}
};
};
/// \brief A unary CallableTransform that wraps its argument
/// in a \c boost::reference_wrapper\<\>.
///
/// Example:
///
/// \code
/// proto::terminal<int>::type i = {42};
/// boost::reference_wrapper<proto::terminal<int>::type> j
/// = proto::when<_, proto::_byref(_)>()(i);
/// assert( boost::addressof(i) == boost::addressof(j.get()) );
/// \endcode
struct _byref : callable
{
template<typename Sig>
struct result;
template<typename This, typename T>
struct result<This(T)>
{
typedef boost::reference_wrapper<T const> const type;
};
template<typename This, typename T>
struct result<This(T &)>
{
typedef boost::reference_wrapper<T> const type;
};
/// Wrap the parameter \c t in a \c boost::reference_wrapper\<\>
/// \param t The object to wrap
/// \return <tt>boost::ref(t)</tt>
/// \throw nothrow
template<typename T>
boost::reference_wrapper<T> const operator ()(T &t) const
{
return boost::reference_wrapper<T>(t);
}
/// \overload
///
template<typename T>
boost::reference_wrapper<T const> const operator ()(T const &t) const
{
return boost::reference_wrapper<T const>(t);
}
};
/// \brief A unary CallableTransform that strips references
/// and \c boost::reference_wrapper\<\> from its argument.
///
/// Example:
///
/// \code
/// proto::terminal<int>::type i = {42};
/// int j = 67;
/// int k = proto::when<_, proto::_byval(proto::_state)>()(i, boost::ref(j));
/// assert( 67 == k );
/// \endcode
struct _byval : callable
{
template<typename Sig>
struct result;
template<typename This, typename T>
struct result<This(T)>
{
typedef T type;
};
template<typename This, typename T>
struct result<This(T &)>
: result<This(T)>
{};
template<typename This, typename T>
struct result<This(boost::reference_wrapper<T>)>
: result<This(T)>
{};
/// \param t The object to unref
/// \return <tt>t</tt>
/// \throw nothrow
template<typename T>
T operator ()(T const &t) const
{
return t;
}
/// \overload
///
template<typename T>
T operator ()(boost::reference_wrapper<T> const &t) const
{
return t;
}
};
/// INTERNAL ONLY
///
template<>
struct is_callable<_expr>
: mpl::true_
{};
/// INTERNAL ONLY
///
template<>
struct is_callable<_state>
: mpl::true_
{};
/// INTERNAL ONLY
///
template<>
struct is_callable<_data>
: mpl::true_
{};
/// INTERNAL ONLY
///
template<int N>
struct is_callable<_child_c<N> >
: mpl::true_
{};
/// INTERNAL ONLY
///
template<>
struct is_callable<_value>
: mpl::true_
{};
/// INTERNAL ONLY
///
template<>
struct is_callable<_byref>
: mpl::true_
{};
/// INTERNAL ONLY
///
template<>
struct is_callable<_byval>
: mpl::true_
{};
}}
#endif

View File

@@ -0,0 +1,424 @@
#ifndef BOOST_PP_IS_ITERATING
///////////////////////////////////////////////////////////////////////////////
/// \file call.hpp
/// Contains definition of the call<> 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_CALL_HPP_EAN_11_02_2007
#define BOOST_PROTO_TRANSFORM_CALL_HPP_EAN_11_02_2007
#include <boost/proto/detail/prefix.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/ref.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/proto/proto_fwd.hpp>
#include <boost/proto/traits.hpp>
#include <boost/proto/transform/impl.hpp>
#include <boost/proto/detail/dont_care.hpp>
#include <boost/proto/detail/as_lvalue.hpp>
#include <boost/proto/detail/poly_function.hpp>
#include <boost/proto/detail/suffix.hpp>
namespace boost { namespace proto
{
/// \brief Wrap \c PrimitiveTransform so that <tt>when\<\></tt> knows
/// it is callable. Requires that the parameter is actually a
/// PrimitiveTransform.
///
/// This form of <tt>call\<\></tt> is useful for annotating an
/// arbitrary PrimitiveTransform as callable when using it with
/// <tt>when\<\></tt>. Consider the following transform, which
/// is parameterized with another transform.
///
/// \code
/// template<typename Grammar>
/// struct Foo
/// : when<
/// unary_plus<Grammar>
/// , Grammar(_child) // May or may not work.
/// >
/// {};
/// \endcode
///
/// The problem with the above is that <tt>when\<\></tt> may or
/// may not recognize \c Grammar as callable, depending on how
/// \c Grammar is implemented. (See <tt>is_callable\<\></tt> for
/// a discussion of this issue.) You can guard against
/// the issue by wrapping \c Grammar in <tt>call\<\></tt>, such
/// as:
///
/// \code
/// template<typename Grammar>
/// struct Foo
/// : when<
/// unary_plus<Grammar>
/// , call<Grammar>(_child) // OK, this works
/// >
/// {};
/// \endcode
///
/// The above could also have been written as:
///
/// \code
/// template<typename Grammar>
/// struct Foo
/// : when<
/// unary_plus<Grammar>
/// , call<Grammar(_child)> // OK, this works, too
/// >
/// {};
/// \endcode
template<typename PrimitiveTransform>
struct call : PrimitiveTransform
{
};
/// \brief Either call the PolymorphicFunctionObject with 0
/// arguments, or invoke the PrimitiveTransform with 3
/// arguments.
template<typename Fun>
struct call<Fun()> : transform<call<Fun()> >
{
/// INTERNAL ONLY
template<typename Expr, typename State, typename Data, bool B>
struct impl2
: transform_impl<Expr, State, Data>
{
typedef typename boost::result_of<Fun()>::type result_type;
result_type operator()(
typename impl2::expr_param
, typename impl2::state_param
, typename impl2::data_param
) const
{
return Fun()();
}
};
/// INTERNAL ONLY
template<typename Expr, typename State, typename Data>
struct impl2<Expr, State, Data, true>
: Fun::template impl<Expr, State, Data>
{};
/// Either call the PolymorphicFunctionObject \c Fun with 0 arguments; or
/// invoke the PrimitiveTransform \c Fun with 3 arguments: the current
/// expression, state, and data.
///
/// If \c Fun is a nullary PolymorphicFunctionObject, return <tt>Fun()()</tt>.
/// Otherwise, return <tt>Fun()(e, s, d)</tt>.
///
/// \param e The current expression
/// \param s The current state
/// \param d An arbitrary data
/// If \c Fun is a nullary PolymorphicFunctionObject, \c type is a typedef
/// for <tt>boost::result_of\<Fun()\>::::type</tt>. Otherwise, it is
/// a typedef for <tt>boost::result_of\<Fun(Expr, State, Data)\>::::type</tt>.
template<typename Expr, typename State, typename Data>
struct impl
: impl2<Expr, State, Data, is_transform<Fun>::value>
{};
};
/// \brief Either call the PolymorphicFunctionObject with 1
/// argument, or invoke the PrimitiveTransform with 3
/// arguments.
template<typename Fun, typename A0>
struct call<Fun(A0)> : transform<call<Fun(A0)> >
{
template<typename Expr, typename State, typename Data, bool B>
struct impl2
: transform_impl<Expr, State, Data>
{
typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
typedef typename detail::as_mono_function<Fun(a0)>::type mono_fun;
typedef typename boost::result_of<mono_fun(a0)>::type result_type;
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
return mono_fun()(
detail::as_lvalue(typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d))
);
}
};
template<typename Expr, typename State, typename Data>
struct impl2<Expr, State, Data, true>
: transform_impl<Expr, State, Data>
{
typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
typedef typename Fun::template impl<a0, State, Data>::result_type result_type;
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
return typename Fun::template impl<a0, State, Data>()(
typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d)
, s
, d
);
}
};
/// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt> and \c X
/// be the type of \c x.
/// If \c Fun is a unary PolymorphicFunctionObject that accepts \c x,
/// then \c type is a typedef for <tt>boost::result_of\<Fun(X)\>::::type</tt>.
/// Otherwise, it is a typedef for <tt>boost::result_of\<Fun(X, State, Data)\>::::type</tt>.
/// Either call the PolymorphicFunctionObject with 1 argument:
/// the result of applying the \c A0 transform; or
/// invoke the PrimitiveTransform with 3 arguments:
/// result of applying the \c A0 transform, the state, and the
/// data.
///
/// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt>.
/// If \c Fun is a unary PolymorphicFunctionObject that accepts \c x,
/// then return <tt>Fun()(x)</tt>. Otherwise, return
/// <tt>Fun()(x, s, d)</tt>.
///
/// \param e The current expression
/// \param s The current state
/// \param d An arbitrary data
template<typename Expr, typename State, typename Data>
struct impl
: impl2<Expr, State, Data, is_transform<Fun>::value>
{};
};
/// \brief Either call the PolymorphicFunctionObject with 2
/// arguments, or invoke the PrimitiveTransform with 3
/// arguments.
template<typename Fun, typename A0, typename A1>
struct call<Fun(A0, A1)> : transform<call<Fun(A0, A1)> >
{
template<typename Expr, typename State, typename Data, bool B>
struct impl2
: transform_impl<Expr, State, Data>
{
typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
typedef typename when<_, A1>::template impl<Expr, State, Data>::result_type a1;
typedef typename detail::as_mono_function<Fun(a0, a1)>::type mono_fun;
typedef typename boost::result_of<mono_fun(a0, a1)>::type result_type;
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
return mono_fun()(
detail::as_lvalue(typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d))
, detail::as_lvalue(typename when<_, A1>::template impl<Expr, State, Data>()(e, s, d))
);
}
};
template<typename Expr, typename State, typename Data>
struct impl2<Expr, State, Data, true>
: transform_impl<Expr, State, Data>
{
typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
typedef typename when<_, A1>::template impl<Expr, State, Data>::result_type a1;
typedef typename Fun::template impl<a0, a1, Data>::result_type result_type;
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
return typename Fun::template impl<a0, a1, Data>()(
typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d)
, typename when<_, A1>::template impl<Expr, State, Data>()(e, s, d)
, d
);
}
};
/// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt> and \c X
/// be the type of \c x.
/// Let \c y be <tt>when\<_, A1\>()(e, s, d)</tt> and \c Y
/// be the type of \c y.
/// If \c Fun is a binary PolymorphicFunction object that accepts \c x
/// and \c y, then \c type is a typedef for
/// <tt>boost::result_of\<Fun(X, Y)\>::::type</tt>. Otherwise, it is
/// a typedef for <tt>boost::result_of\<Fun(X, Y, Data)\>::::type</tt>.
/// Either call the PolymorphicFunctionObject with 2 arguments:
/// the result of applying the \c A0 transform, and the
/// result of applying the \c A1 transform; or invoke the
/// PrimitiveTransform with 3 arguments: the result of applying
/// the \c A0 transform, the result of applying the \c A1
/// transform, and the data.
///
/// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt>.
/// Let \c y be <tt>when\<_, A1\>()(e, s, d)</tt>.
/// If \c Fun is a binary PolymorphicFunction object that accepts \c x
/// and \c y, return <tt>Fun()(x, y)</tt>. Otherwise, return
/// <tt>Fun()(x, y, d)</tt>.
///
/// \param e The current expression
/// \param s The current state
/// \param d An arbitrary data
template<typename Expr, typename State, typename Data>
struct impl
: impl2<Expr, State, Data, is_transform<Fun>::value>
{};
};
/// \brief Call the PolymorphicFunctionObject or the
/// PrimitiveTransform with the current expression, state
/// and data, transformed according to \c A0, \c A1, and
/// \c A2, respectively.
template<typename Fun, typename A0, typename A1, typename A2>
struct call<Fun(A0, A1, A2)> : transform<call<Fun(A0, A1, A2)> >
{
template<typename Expr, typename State, typename Data, bool B>
struct impl2
: transform_impl<Expr, State, Data>
{
typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
typedef typename when<_, A1>::template impl<Expr, State, Data>::result_type a1;
typedef typename when<_, A2>::template impl<Expr, State, Data>::result_type a2;
typedef typename detail::as_mono_function<Fun(a0, a1, a2)>::type mono_fun;
typedef typename boost::result_of<mono_fun(a0, a1, a2)>::type result_type;
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
return mono_fun()(
detail::as_lvalue(typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d))
, detail::as_lvalue(typename when<_, A1>::template impl<Expr, State, Data>()(e, s, d))
, detail::as_lvalue(typename when<_, A2>::template impl<Expr, State, Data>()(e, s, d))
);
}
};
template<typename Expr, typename State, typename Data>
struct impl2<Expr, State, Data, true>
: transform_impl<Expr, State, Data>
{
typedef typename when<_, A0>::template impl<Expr, State, Data>::result_type a0;
typedef typename when<_, A1>::template impl<Expr, State, Data>::result_type a1;
typedef typename when<_, A2>::template impl<Expr, State, Data>::result_type a2;
typedef typename Fun::template impl<a0, a1, a2>::result_type result_type;
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
return typename Fun::template impl<a0, a1, a2>()(
typename when<_, A0>::template impl<Expr, State, Data>()(e, s, d)
, typename when<_, A1>::template impl<Expr, State, Data>()(e, s, d)
, typename when<_, A2>::template impl<Expr, State, Data>()(e, s, d)
);
}
};
/// Let \c x be <tt>when\<_, A0\>()(e, s, d)</tt>.
/// Let \c y be <tt>when\<_, A1\>()(e, s, d)</tt>.
/// Let \c z be <tt>when\<_, A2\>()(e, s, d)</tt>.
/// Return <tt>Fun()(x, y, z)</tt>.
///
/// \param e The current expression
/// \param s The current state
/// \param d An arbitrary data
template<typename Expr, typename State, typename Data>
struct impl
: impl2<Expr, State, Data, is_transform<Fun>::value>
{};
};
#if BOOST_PROTO_MAX_ARITY > 3
#define BOOST_PP_ITERATION_PARAMS_1 (3, (4, BOOST_PROTO_MAX_ARITY, <boost/proto/transform/call.hpp>))
#include BOOST_PP_ITERATE()
#endif
/// INTERNAL ONLY
///
template<typename Fun>
struct is_callable<call<Fun> >
: mpl::true_
{};
}} // namespace boost::proto
#endif
#else
#define N BOOST_PP_ITERATION()
/// \brief Call the PolymorphicFunctionObject \c Fun with the
/// current expression, state and data, transformed according
/// to \c A0 through \c AN.
template<typename Fun BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
struct call<Fun(BOOST_PP_ENUM_PARAMS(N, A))> : transform<call<Fun(BOOST_PP_ENUM_PARAMS(N, A))> >
{
template<typename Expr, typename State, typename Data>
struct impl : transform_impl<Expr, State, Data>
{
#define M0(Z, M, DATA) \
typedef \
typename when<_, BOOST_PP_CAT(A, M)> \
::template impl<Expr, State, Data> \
::result_type \
BOOST_PP_CAT(a, M); \
/**/
BOOST_PP_REPEAT(N, M0, ~)
#undef M0
typedef
typename detail::as_mono_function<Fun(BOOST_PP_ENUM_PARAMS(N, a))>::type
mono_fun;
typedef
typename boost::result_of<mono_fun(BOOST_PP_ENUM_PARAMS(N, a))>::type
result_type;
/// Let \c ax be <tt>when\<_, Ax\>()(e, s, d)</tt>
/// for each \c x in <tt>[0,N]</tt>.
/// Return <tt>Fun()(a0, a1,... aN)</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
{
#define M0(Z, M, DATA) \
detail::as_lvalue( \
typename when<_, BOOST_PP_CAT(A, M)> \
::template impl<Expr, State, Data>()(e, s, d)) \
/**/
return mono_fun()(BOOST_PP_ENUM(N, M0, ~));
#undef M0
}
};
};
#undef N
#endif

View File

@@ -0,0 +1,525 @@
#ifndef BOOST_PP_IS_ITERATING
///////////////////////////////////////////////////////////////////////////////
/// \file default.hpp
/// Contains definition of the _default transform, which gives operators their
/// usual C++ meanings and uses Boost.Typeof to deduce return types.
//
// 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_DEFAULT_HPP_EAN_04_04_2008
#define BOOST_PROTO_TRANSFORM_DEFAULT_HPP_EAN_04_04_2008
#include <boost/proto/detail/prefix.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/enum_shifted.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/ref.hpp>
#include <boost/get_pointer.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_member_pointer.hpp>
#include <boost/type_traits/is_member_object_pointer.hpp>
#include <boost/type_traits/is_member_function_pointer.hpp>
#include <boost/proto/proto_fwd.hpp>
#include <boost/proto/traits.hpp>
#include <boost/proto/transform/impl.hpp>
#include <boost/proto/transform/arg.hpp>
#include <boost/proto/detail/decltype.hpp>
#include <boost/proto/detail/suffix.hpp>
namespace boost { namespace proto
{
template<typename Grammar>
struct _default
: transform<_default<Grammar> >
{
template<typename Expr, typename State, typename Data, typename Tag, long Arity>
struct impl2;
template<typename Expr, typename State, typename Data, typename Tag>
struct impl2<Expr, State, Data, Tag, 0>
: _value::impl<Expr, State, Data>
{};
#define BOOST_PROTO_UNARY_OP_RESULT(OP, TAG, MAKE) \
template<typename Expr, typename State, typename Data> \
struct impl2<Expr, State, Data, TAG, 1> \
: transform_impl<Expr, State, Data> \
{ \
private: \
typedef typename result_of::child_c<Expr, 0>::type e0; \
typedef typename Grammar::template impl<e0, State, Data>::result_type r0; \
public: \
BOOST_PROTO_DECLTYPE_(OP proto::detail::MAKE<r0>(), result_type) \
result_type operator ()( \
typename impl2::expr_param e \
, typename impl2::state_param s \
, typename impl2::data_param d \
) const \
{ \
typename Grammar::template impl<e0, State, Data> t0; \
return OP t0(proto::child_c<0>(e), s, d); \
} \
}; \
/**/
#define BOOST_PROTO_BINARY_OP_RESULT(OP, TAG, LMAKE, RMAKE) \
template<typename Expr, typename State, typename Data> \
struct impl2<Expr, State, Data, TAG, 2> \
: transform_impl<Expr, State, Data> \
{ \
private: \
typedef typename result_of::child_c<Expr, 0>::type e0; \
typedef typename result_of::child_c<Expr, 1>::type e1; \
typedef typename Grammar::template impl<e0, State, Data>::result_type r0; \
typedef typename Grammar::template impl<e1, State, Data>::result_type r1; \
public: \
BOOST_PROTO_DECLTYPE_( \
proto::detail::LMAKE<r0>() OP proto::detail::RMAKE<r1>() \
, result_type \
) \
result_type operator ()( \
typename impl2::expr_param e \
, typename impl2::state_param s \
, typename impl2::data_param d \
) const \
{ \
typename Grammar::template impl<e0, State, Data> t0; \
typename Grammar::template impl<e1, State, Data> t1; \
return t0(proto::child_c<0>(e), s, d) \
OP t1(proto::child_c<1>(e), s, d); \
} \
}; \
/**/
BOOST_PROTO_UNARY_OP_RESULT(+, tag::unary_plus, make)
BOOST_PROTO_UNARY_OP_RESULT(-, tag::negate, make)
BOOST_PROTO_UNARY_OP_RESULT(*, tag::dereference, make)
BOOST_PROTO_UNARY_OP_RESULT(~, tag::complement, make)
BOOST_PROTO_UNARY_OP_RESULT(&, tag::address_of, make)
BOOST_PROTO_UNARY_OP_RESULT(!, tag::logical_not, make)
BOOST_PROTO_UNARY_OP_RESULT(++, tag::pre_inc, make_mutable)
BOOST_PROTO_UNARY_OP_RESULT(--, tag::pre_dec, make_mutable)
BOOST_PROTO_BINARY_OP_RESULT(<<, tag::shift_left, make_mutable, make)
BOOST_PROTO_BINARY_OP_RESULT(>>, tag::shift_right, make_mutable, make_mutable)
BOOST_PROTO_BINARY_OP_RESULT(*, tag::multiplies, make, make)
BOOST_PROTO_BINARY_OP_RESULT(/, tag::divides, make, make)
BOOST_PROTO_BINARY_OP_RESULT(%, tag::modulus, make, make)
BOOST_PROTO_BINARY_OP_RESULT(+, tag::plus, make, make)
BOOST_PROTO_BINARY_OP_RESULT(-, tag::minus, make, make)
BOOST_PROTO_BINARY_OP_RESULT(<, tag::less, make, make)
BOOST_PROTO_BINARY_OP_RESULT(>, tag::greater, make, make)
BOOST_PROTO_BINARY_OP_RESULT(<=, tag::less_equal, make, make)
BOOST_PROTO_BINARY_OP_RESULT(>=, tag::greater_equal, make, make)
BOOST_PROTO_BINARY_OP_RESULT(==, tag::equal_to, make, make)
BOOST_PROTO_BINARY_OP_RESULT(!=, tag::not_equal_to, make, make)
BOOST_PROTO_BINARY_OP_RESULT(||, tag::logical_or, make, make)
BOOST_PROTO_BINARY_OP_RESULT(&&, tag::logical_and, make, make)
BOOST_PROTO_BINARY_OP_RESULT(&, tag::bitwise_and, make, make)
BOOST_PROTO_BINARY_OP_RESULT(|, tag::bitwise_or, make, make)
BOOST_PROTO_BINARY_OP_RESULT(^, tag::bitwise_xor, make, make)
BOOST_PROTO_BINARY_OP_RESULT(=, tag::assign, make_mutable, make)
BOOST_PROTO_BINARY_OP_RESULT(<<=, tag::shift_left_assign, make_mutable, make)
BOOST_PROTO_BINARY_OP_RESULT(>>=, tag::shift_right_assign, make_mutable, make)
BOOST_PROTO_BINARY_OP_RESULT(*=, tag::multiplies_assign, make_mutable, make)
BOOST_PROTO_BINARY_OP_RESULT(/=, tag::divides_assign, make_mutable, make)
BOOST_PROTO_BINARY_OP_RESULT(%=, tag::modulus_assign, make_mutable, make)
BOOST_PROTO_BINARY_OP_RESULT(+=, tag::plus_assign, make_mutable, make)
BOOST_PROTO_BINARY_OP_RESULT(-=, tag::minus_assign, make_mutable, make)
BOOST_PROTO_BINARY_OP_RESULT(&=, tag::bitwise_and_assign, make_mutable, make)
BOOST_PROTO_BINARY_OP_RESULT(|=, tag::bitwise_or_assign, make_mutable, make)
BOOST_PROTO_BINARY_OP_RESULT(^=, tag::bitwise_xor_assign, make_mutable, make)
#undef BOOST_PROTO_UNARY_OP_RESULT
#undef BOOST_PROTO_BINARY_OP_RESULT
/// INTERNAL ONLY
template<typename Expr, typename State, typename Data>
struct is_member_function_invocation
{
typedef typename result_of::child_c<Expr, 1>::type e1;
typedef typename Grammar::template impl<e1, State, Data>::result_type r1;
typedef typename remove_const<typename remove_reference<r1>::type>::type uncvref_r1;
typedef typename is_member_function_pointer<uncvref_r1>::type type;
BOOST_STATIC_CONSTANT(bool, value = type::value);
};
/// INTERNAL ONLY
template<typename Expr, typename State, typename Data, bool IsMemFunCall>
struct memfun_impl
: transform_impl<Expr, State, Data>
{
private:
typedef typename result_of::child_c<Expr, 0>::type e0;
typedef typename result_of::child_c<Expr, 1>::type e1;
typedef typename Grammar::template impl<e0, State, Data>::result_type r0;
typedef typename Grammar::template impl<e1, State, Data>::result_type r1;
public:
typedef typename detail::mem_ptr_fun<r0, r1>::result_type result_type;
result_type operator ()(
typename memfun_impl::expr_param e
, typename memfun_impl::state_param s
, typename memfun_impl::data_param d
) const
{
typename Grammar::template impl<e0, State, Data> t0;
typename Grammar::template impl<e1, State, Data> t1;
return detail::mem_ptr_fun<r0, r1>()(
t0(proto::child_c<0>(e), s, d)
, t1(proto::child_c<1>(e), s, d)
);
}
};
/// INTERNAL ONLY
template<typename Expr, typename State, typename Data>
struct memfun_impl<Expr, State, Data, true>
: transform_impl<Expr, State, Data>
{
private:
typedef typename result_of::child_c<Expr, 0>::type e0;
typedef typename result_of::child_c<Expr, 1>::type e1;
typedef typename Grammar::template impl<e0, State, Data>::result_type r0;
typedef typename Grammar::template impl<e1, State, Data>::result_type r1;
public:
typedef detail::memfun<r0, r1> result_type;
result_type const operator ()(
typename memfun_impl::expr_param e
, typename memfun_impl::state_param s
, typename memfun_impl::data_param d
) const
{
typename Grammar::template impl<e0, State, Data> t0;
typename Grammar::template impl<e1, State, Data> t1;
return detail::memfun<r0, r1>(
t0(proto::child_c<0>(e), s, d)
, t1(proto::child_c<1>(e), s, d)
);
}
};
template<typename Expr, typename State, typename Data>
struct impl2<Expr, State, Data, tag::mem_ptr, 2>
: memfun_impl<Expr, State, Data, is_member_function_invocation<Expr, State, Data>::value>
{};
template<typename Expr, typename State, typename Data>
struct impl2<Expr, State, Data, tag::post_inc, 1>
: transform_impl<Expr, State, Data>
{
private:
typedef typename result_of::child_c<Expr, 0>::type e0;
typedef typename Grammar::template impl<e0, State, Data>::result_type r0;
public:
BOOST_PROTO_DECLTYPE_(proto::detail::make_mutable<r0>() ++, result_type)
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
typename Grammar::template impl<e0, State, Data> t0;
return t0(proto::child_c<0>(e), s, d) ++;
}
};
template<typename Expr, typename State, typename Data>
struct impl2<Expr, State, Data, tag::post_dec, 1>
: transform_impl<Expr, State, Data>
{
private:
typedef typename result_of::child_c<Expr, 0>::type e0;
typedef typename Grammar::template impl<e0, State, Data>::result_type r0;
public:
BOOST_PROTO_DECLTYPE_(proto::detail::make_mutable<r0>() --, result_type)
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
typename Grammar::template impl<e0, State, Data> t0;
return t0(proto::child_c<0>(e), s, d) --;
}
};
template<typename Expr, typename State, typename Data>
struct impl2<Expr, State, Data, tag::subscript, 2>
: transform_impl<Expr, State, Data>
{
private:
typedef typename result_of::child_c<Expr, 0>::type e0;
typedef typename result_of::child_c<Expr, 1>::type e1;
typedef typename Grammar::template impl<e0, State, Data>::result_type r0;
typedef typename Grammar::template impl<e1, State, Data>::result_type r1;
public:
BOOST_PROTO_DECLTYPE_(
proto::detail::make_subscriptable<r0>() [ proto::detail::make<r1>() ]
, result_type
)
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
typename Grammar::template impl<e0, State, Data> t0;
typename Grammar::template impl<e1, State, Data> t1;
return t0(proto::child_c<0>(e), s, d) [
t1(proto::child_c<1>(e), s, d) ];
}
};
template<typename Expr, typename State, typename Data>
struct impl2<Expr, State, Data, tag::if_else_, 3>
: transform_impl<Expr, State, Data>
{
private:
typedef typename result_of::child_c<Expr, 0>::type e0;
typedef typename result_of::child_c<Expr, 1>::type e1;
typedef typename result_of::child_c<Expr, 2>::type e2;
typedef typename Grammar::template impl<e0, State, Data>::result_type r0;
typedef typename Grammar::template impl<e1, State, Data>::result_type r1;
typedef typename Grammar::template impl<e2, State, Data>::result_type r2;
public:
BOOST_PROTO_DECLTYPE_(
proto::detail::make<r0>()
? proto::detail::make<r1>()
: proto::detail::make<r2>()
, result_type
)
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
typename Grammar::template impl<e0, State, Data> t0;
typename Grammar::template impl<e1, State, Data> t1;
typename Grammar::template impl<e2, State, Data> t2;
return t0(proto::child_c<0>(e), s, d)
? t1(proto::child_c<1>(e), s, d)
: t2(proto::child_c<2>(e), s, d);
}
};
template<typename Expr, typename State, typename Data>
struct impl2<Expr, State, Data, tag::comma, 2>
: transform_impl<Expr, State, Data>
{
private:
typedef typename result_of::child_c<Expr, 0>::type e0;
typedef typename result_of::child_c<Expr, 1>::type e1;
typedef typename Grammar::template impl<e0, State, Data>::result_type r0;
typedef typename Grammar::template impl<e1, State, Data>::result_type r1;
public:
typedef typename proto::detail::comma_result<r0, r1>::type result_type;
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
typename Grammar::template impl<e0, State, Data> t0;
typename Grammar::template impl<e1, State, Data> t1;
return t0(proto::child_c<0>(e), s, d)
, t1(proto::child_c<1>(e), s, d);
}
};
#define EVAL_TYPE(Z, N, DATA) \
typedef \
typename result_of::child_c<DATA, N>::type \
BOOST_PP_CAT(e, N); \
typedef \
typename Grammar::template impl<BOOST_PP_CAT(e, N), State, Data>::result_type \
BOOST_PP_CAT(r, N); \
/**/
#define EVAL(Z, N, DATA) \
typename Grammar::template impl<BOOST_PP_CAT(e, N), State, Data>()( \
proto::child_c<N>(DATA), s, d \
) \
/**/
template<typename Expr, typename State, typename Data>
struct impl2<Expr, State, Data, tag::function, 1>
: transform_impl<Expr, State, Data>
{
EVAL_TYPE(~, 0, Expr)
typedef
typename proto::detail::result_of_fixup<r0>::type
function_type;
typedef
typename boost::result_of<function_type()>::type
result_type;
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
return EVAL(~, 0, e)();
}
};
template<typename Expr, typename State, typename Data>
struct impl2<Expr, State, Data, tag::function, 2>
: transform_impl<Expr, State, Data>
{
EVAL_TYPE(~, 0, Expr)
EVAL_TYPE(~, 1, Expr)
typedef
typename proto::detail::result_of_fixup<r0>::type
function_type;
typedef
typename detail::result_of_<function_type(r1)>::type
result_type;
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
return this->invoke(
e
, s
, d
, is_member_function_pointer<function_type>()
, is_member_object_pointer<function_type>()
);
}
private:
result_type invoke(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
, mpl::false_
, mpl::false_
) const
{
return EVAL(~, 0, e)(EVAL(~, 1, e));
}
result_type invoke(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
, mpl::true_
, mpl::false_
) const
{
using namespace detail::get_pointer_;
return (get_pointer(EVAL(~, 1, e)) ->* EVAL(~, 0, e))();
}
result_type invoke(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
, mpl::false_
, mpl::true_
) const
{
using namespace detail::get_pointer_;
return (get_pointer(EVAL(~, 1, e)) ->* EVAL(~, 0, e));
}
};
#define BOOST_PP_ITERATION_PARAMS_1 (3, (3, BOOST_PROTO_MAX_ARITY, <boost/proto/transform/default.hpp>))
#include BOOST_PP_ITERATE()
#undef EVAL_TYPE
#undef EVAL
template<typename Expr, typename State, typename Data>
struct impl
: impl2<
Expr
, State
, Data
, typename transform_impl<Expr, State, Data>::expr::proto_tag
, transform_impl<Expr, State, Data>::expr::proto_arity_c
>
{};
};
template<typename Grammar>
struct is_callable<_default<Grammar> >
: mpl::true_
{};
}}
#endif
#else
#define N BOOST_PP_ITERATION()
template<typename Expr, typename State, typename Data>
struct impl2<Expr, State, Data, tag::function, N>
: transform_impl<Expr, State, Data>
{
BOOST_PP_REPEAT(N, EVAL_TYPE, Expr)
typedef
typename proto::detail::result_of_fixup<r0>::type
function_type;
typedef
typename boost::result_of<
function_type(BOOST_PP_ENUM_SHIFTED_PARAMS(N, r))
>::type
result_type;
result_type operator ()(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
) const
{
return this->invoke(e, s, d, is_member_function_pointer<function_type>());
}
private:
result_type invoke(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
, mpl::false_
) const
{
return EVAL(~, 0, e)(BOOST_PP_ENUM_SHIFTED(N, EVAL, e));
}
result_type invoke(
typename impl2::expr_param e
, typename impl2::state_param s
, typename impl2::data_param d
, mpl::true_
) const
{
#define M0(Z, M, e) BOOST_PP_COMMA_IF(BOOST_PP_SUB(M, 2)) EVAL(Z, M, e)
using namespace detail::get_pointer_;
return (get_pointer(EVAL(~, 1, e)) ->* EVAL(~, 0, e))(
BOOST_PP_REPEAT_FROM_TO(2, N, M0, e)
);
#undef M0
}
};
#undef N
#endif

View File

@@ -0,0 +1,361 @@
#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/proto/detail/prefix.hpp>
#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>
#if BOOST_VERSION >= 103500
#include <boost/fusion/include/fold.hpp>
#else
#include <boost/spirit/fusion/algorithm/fold.hpp>
#endif
#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>
#include <boost/proto/detail/suffix.hpp>
namespace boost { namespace proto
{
namespace detail
{
template<typename Transform, typename Data>
struct as_callable
{
as_callable(Data v)
: v_(v)
{}
template<typename Sig>
struct result;
template<typename This, typename Expr, typename State>
struct result<This(Expr, State)>
{
typedef
typename when<_, Transform>::template impl<Expr, State, Data>::result_type
type;
};
#if BOOST_VERSION < 103500
template<typename Expr, typename State>
struct apply
: result<void(Expr, State)>
{};
#endif
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->v_);
}
private:
Data v_;
};
#if BOOST_VERSION < 103500
template<typename Sequence, typename Void = void>
struct as_fusion_sequence_type
{
typedef Sequence const type;
};
template<typename Sequence>
Sequence const &as_fusion_sequence(Sequence const &sequence, ...)
{
return sequence;
}
template<typename Sequence>
struct as_fusion_sequence_type<Sequence, typename Sequence::proto_is_expr_>
{
typedef typename Sequence::proto_base_expr const type;
};
template<typename Sequence>
typename Sequence::proto_base_expr const &as_fusion_sequence(Sequence const &sequence, int)
{
return sequence.proto_base();
}
#define BOOST_PROTO_AS_FUSION_SEQUENCE_TYPE(X) typename detail::as_fusion_sequence_type<X>::type
#define BOOST_PROTO_AS_FUSION_SEQUENCE(X) detail::as_fusion_sequence(X, 0)
#else
#define BOOST_PROTO_AS_FUSION_SEQUENCE_TYPE(X) X
#define BOOST_PROTO_AS_FUSION_SEQUENCE(X) X
#endif
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(v)(e,s) == when\<_,Fun\>()(e,s,v)</tt>
typedef
detail::as_callable<Fun, Data>
fun;
typedef
typename fusion::BOOST_PROTO_FUSION_RESULT_OF::fold<
BOOST_PROTO_AS_FUSION_SEQUENCE_TYPE(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(
BOOST_PROTO_AS_FUSION_SEQUENCE(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

View File

@@ -0,0 +1,174 @@
///////////////////////////////////////////////////////////////////////////////
/// \file fold_tree.hpp
/// Contains definition of the fold_tree<> and reverse_fold_tree<> 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_TREE_HPP_EAN_11_05_2007
#define BOOST_PROTO_TRANSFORM_FOLD_TREE_HPP_EAN_11_05_2007
#include <boost/proto/detail/prefix.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/proto/proto_fwd.hpp>
#include <boost/proto/traits.hpp>
#include <boost/proto/matches.hpp>
#include <boost/proto/transform/fold.hpp>
#include <boost/proto/transform/impl.hpp>
#include <boost/proto/detail/suffix.hpp>
namespace boost { namespace proto
{
namespace detail
{
template<typename Tag>
struct has_tag : transform<has_tag<Tag> >
{
template<typename Expr, typename State, typename Data, typename EnableIf = Tag>
struct impl
: transform_impl<Expr, State, Data>
{
typedef mpl::false_ result_type;
};
template<typename Expr, typename State, typename Data>
struct impl<Expr, State, Data, typename Expr::proto_tag>
: transform_impl<Expr, State, Data>
{
typedef mpl::true_ result_type;
};
template<typename Expr, typename State, typename Data>
struct impl<Expr &, State, Data, typename Expr::proto_tag>
: transform_impl<Expr &, State, Data>
{
typedef mpl::true_ result_type;
};
};
template<typename Tag, typename Fun>
struct fold_tree_
: if_<has_tag<Tag>, fold<_, _state, fold_tree_<Tag, Fun> >, Fun>
{};
template<typename Tag, typename Fun>
struct reverse_fold_tree_
: if_<has_tag<Tag>, reverse_fold<_, _state, reverse_fold_tree_<Tag, Fun> >, Fun>
{};
}
/// \brief A PrimitiveTransform that recursively applies the
/// <tt>fold\<\></tt> transform to sub-trees that all share a common
/// tag type.
///
/// <tt>fold_tree\<\></tt> is useful for flattening trees into lists;
/// for example, you might use <tt>fold_tree\<\></tt> to flatten an
/// expression tree like <tt>a | b | c</tt> into a Fusion list like
/// <tt>cons(c, cons(b, cons(a)))</tt>.
///
/// <tt>fold_tree\<\></tt> is easily understood in terms of a
/// <tt>recurse_if_\<\></tt> helper, defined as follows:
///
/// \code
/// template<typename Tag, typename Fun>
/// struct recurse_if_
/// : if_<
/// // If the current node has type type "Tag" ...
/// is_same<tag_of<_>, Tag>()
/// // ... recurse, otherwise ...
/// , fold<_, _state, recurse_if_<Tag, Fun> >
/// // ... apply the Fun transform.
/// , Fun
/// >
/// {};
/// \endcode
///
/// With <tt>recurse_if_\<\></tt> as defined above,
/// <tt>fold_tree\<Sequence, State0, Fun\>()(e, s, d)</tt> is
/// equivalent to
/// <tt>fold<Sequence, State0, recurse_if_<Expr::proto_tag, Fun> >()(e, s, d).</tt>
/// It has the effect of folding a tree front-to-back, recursing into
/// child nodes that share a tag type with the parent node.
template<typename Sequence, typename State0, typename Fun>
struct fold_tree
: transform<fold_tree<Sequence, State0, Fun> >
{
template<typename Expr, typename State, typename Data>
struct impl
: fold<
Sequence
, State0
, detail::fold_tree_<
typename remove_reference<Expr>::type::proto_tag
, Fun
>
>::template impl<Expr, State, Data>
{};
};
/// \brief A PrimitiveTransform that recursively applies the
/// <tt>reverse_fold\<\></tt> transform to sub-trees that all share
/// a common tag type.
///
/// <tt>reverse_fold_tree\<\></tt> is useful for flattening trees into
/// lists; for example, you might use <tt>reverse_fold_tree\<\></tt> to
/// flatten an expression tree like <tt>a | b | c</tt> into a Fusion list
/// like <tt>cons(a, cons(b, cons(c)))</tt>.
///
/// <tt>reverse_fold_tree\<\></tt> is easily understood in terms of a
/// <tt>recurse_if_\<\></tt> helper, defined as follows:
///
/// \code
/// template<typename Tag, typename Fun>
/// struct recurse_if_
/// : if_<
/// // If the current node has type type "Tag" ...
/// is_same<tag_of<_>, Tag>()
/// // ... recurse, otherwise ...
/// , reverse_fold<_, _state, recurse_if_<Tag, Fun> >
/// // ... apply the Fun transform.
/// , Fun
/// >
/// {};
/// \endcode
///
/// With <tt>recurse_if_\<\></tt> as defined above,
/// <tt>reverse_fold_tree\<Sequence, State0, Fun\>()(e, s, d)</tt> is
/// equivalent to
/// <tt>reverse_fold<Sequence, State0, recurse_if_<Expr::proto_tag, Fun> >()(e, s, d).</tt>
/// It has the effect of folding a tree back-to-front, recursing into
/// child nodes that share a tag type with the parent node.
template<typename Sequence, typename State0, typename Fun>
struct reverse_fold_tree
: transform<reverse_fold_tree<Sequence, State0, Fun> >
{
template<typename Expr, typename State, typename Data>
struct impl
: reverse_fold<
Sequence
, State0
, detail::reverse_fold_tree_<
typename remove_reference<Expr>::type::proto_tag
, Fun
>
>::template impl<Expr, State, Data>
{};
};
/// INTERNAL ONLY
///
template<typename Sequence, typename State0, typename Fun>
struct is_callable<fold_tree<Sequence, State0, Fun> >
: mpl::true_
{};
/// INTERNAL ONLY
///
template<typename Sequence, typename State0, typename Fun>
struct is_callable<reverse_fold_tree<Sequence, State0, Fun> >
: mpl::true_
{};
}}
#endif

View File

@@ -0,0 +1,190 @@
///////////////////////////////////////////////////////////////////////////////
/// \file impl.hpp
/// Contains definition of transform<> and transform_impl<> helpers.
//
// 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_IMPL_HPP_EAN_04_03_2008
#define BOOST_PROTO_TRANSFORM_IMPL_HPP_EAN_04_03_2008
#include <boost/proto/detail/prefix.hpp>
#include <boost/proto/proto_fwd.hpp>
#include <boost/proto/detail/suffix.hpp>
namespace boost { namespace proto
{
template<typename PrimitiveTransform, typename Expr, typename State = int, typename Data = int>
struct apply_transform
: PrimitiveTransform::template impl<Expr, State, Data>
{};
struct transform_base
{
BOOST_PROTO_CALLABLE()
BOOST_PROTO_TRANSFORM()
};
struct empty_base
{};
template<
typename PrimitiveTransform
, typename Base BOOST_PROTO_WHEN_BUILDING_DOCS(= transform_base)
>
struct transform : Base
{
typedef PrimitiveTransform transform_type;
template<typename Sig>
struct result;
template<typename This, typename Expr>
struct result<This(Expr)>
{
typedef typename PrimitiveTransform::template impl<Expr, int, int>::result_type type;
};
template<typename This, typename Expr, typename State>
struct result<This(Expr, State)>
{
typedef typename PrimitiveTransform::template impl<Expr, State, int>::result_type type;
};
template<typename This, typename Expr, typename State, typename Data>
struct result<This(Expr, State, Data)>
{
typedef typename PrimitiveTransform::template impl<Expr, State, Data>::result_type type;
};
template<typename Expr>
typename apply_transform<PrimitiveTransform, Expr &>::result_type
operator ()(Expr &e) const
{
int i = 0;
return apply_transform<PrimitiveTransform, Expr &>()(e, i, i);
}
template<typename Expr, typename State>
typename apply_transform<PrimitiveTransform, Expr &, State &>::result_type
operator ()(Expr &e, State &s) const
{
int i = 0;
return apply_transform<PrimitiveTransform, Expr &, State &>()(e, s, i);
}
template<typename Expr, typename State>
typename apply_transform<PrimitiveTransform, Expr &, State const &>::result_type
operator ()(Expr &e, State const &s) const
{
int i = 0;
return apply_transform<PrimitiveTransform, Expr &, State const &>()(e, s, i);
}
template<typename Expr, typename State, typename Data>
typename apply_transform<PrimitiveTransform, Expr &, State &, Data &>::result_type
operator ()(Expr &e, State &s, Data &d) const
{
return apply_transform<PrimitiveTransform, Expr &, State &, Data &>()(e, s, d);
}
template<typename Expr, typename State, typename Data>
typename apply_transform<PrimitiveTransform, Expr &, State const &, Data &>::result_type
operator ()(Expr &e, State const &s, Data &d) const
{
return apply_transform<PrimitiveTransform, Expr &, State const &, Data &>()(e, s, d);
}
};
template<typename Expr, typename State, typename Data>
struct transform_impl
{
typedef Expr const expr;
typedef Expr const &expr_param;
typedef State const state;
typedef State const &state_param;
typedef Data const data;
typedef Data const &data_param;
};
template<typename Expr, typename State, typename Data>
struct transform_impl<Expr &, State, Data>
{
typedef Expr expr;
typedef Expr &expr_param;
typedef State const state;
typedef State const &state_param;
typedef Data const data;
typedef Data const &data_param;
};
template<typename Expr, typename State, typename Data>
struct transform_impl<Expr, State &, Data>
{
typedef Expr const expr;
typedef Expr const &expr_param;
typedef State state;
typedef State &state_param;
typedef Data const data;
typedef Data const &data_param;
};
template<typename Expr, typename State, typename Data>
struct transform_impl<Expr, State, Data &>
{
typedef Expr const expr;
typedef Expr const &expr_param;
typedef State const state;
typedef State const &state_param;
typedef Data data;
typedef Data &data_param;
};
template<typename Expr, typename State, typename Data>
struct transform_impl<Expr &, State &, Data>
{
typedef Expr expr;
typedef Expr &expr_param;
typedef State state;
typedef State &state_param;
typedef Data const data;
typedef Data const &data_param;
};
template<typename Expr, typename State, typename Data>
struct transform_impl<Expr &, State, Data &>
{
typedef Expr expr;
typedef Expr &expr_param;
typedef State const state;
typedef State const &state_param;
typedef Data data;
typedef Data &data_param;
};
template<typename Expr, typename State, typename Data>
struct transform_impl<Expr, State &, Data &>
{
typedef Expr const expr;
typedef Expr const &expr_param;
typedef State state;
typedef State &state_param;
typedef Data data;
typedef Data &data_param;
};
template<typename Expr, typename State, typename Data>
struct transform_impl<Expr &, State &, Data &>
{
typedef Expr expr;
typedef Expr &expr_param;
typedef State state;
typedef State &state_param;
typedef Data data;
typedef Data &data_param;
};
}} // namespace boost::proto
#endif

View File

@@ -0,0 +1,85 @@
#ifndef BOOST_PP_IS_ITERATING
///////////////////////////////////////////////////////////////////////////////
/// \file lazy.hpp
/// Contains definition of the lazy<> 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_LAZY_HPP_EAN_12_02_2007
#define BOOST_PROTO_TRANSFORM_LAZY_HPP_EAN_12_02_2007
#include <boost/proto/detail/prefix.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/proto/proto_fwd.hpp>
#include <boost/proto/transform/make.hpp>
#include <boost/proto/transform/call.hpp>
#include <boost/proto/transform/impl.hpp>
#include <boost/proto/detail/suffix.hpp>
namespace boost { namespace proto
{
/// \brief A PrimitiveTransform that uses <tt>make\<\></tt> to build
/// a CallableTransform, and then uses <tt>call\<\></tt> to apply it.
///
/// <tt>lazy\<\></tt> is useful as a higher-order transform, when the
/// transform to be applied depends on the current state of the
/// transformation. The invocation of the <tt>make\<\></tt> transform
/// evaluates any nested transforms, and the resulting type is treated
/// as a CallableTransform, which is evaluated with <tt>call\<\></tt>.
template<typename Object>
struct lazy : transform<lazy<Object> >
{
template<typename Expr, typename State, typename Data>
struct impl
: call<
typename make<Object>::template impl<Expr, State, Data>::result_type
>::template impl<Expr, State, Data>
{};
};
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PROTO_MAX_ARITY, <boost/proto/transform/lazy.hpp>))
#include BOOST_PP_ITERATE()
/// INTERNAL ONLY
///
template<typename Object>
struct is_callable<lazy<Object> >
: mpl::true_
{};
}}
#endif
#else
#define N BOOST_PP_ITERATION()
/// \brief A PrimitiveTransform that uses <tt>make\<\></tt> to build
/// a CallableTransform, and then uses <tt>call\<\></tt> to apply it.
///
/// <tt>lazy\<\></tt> is useful as a higher-order transform, when the
/// transform to be applied depends on the current state of the
/// transformation. The invocation of the <tt>make\<\></tt> transform
/// evaluates any nested transforms, and the resulting type is treated
/// as a CallableTransform, which is evaluated with <tt>call\<\></tt>.
template<typename Object BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
struct lazy<Object(BOOST_PP_ENUM_PARAMS(N, A))>
: transform<lazy<Object(BOOST_PP_ENUM_PARAMS(N, A))> >
{
template<typename Expr, typename State, typename Data>
struct impl
: call<
typename make<Object>::template impl<Expr, State, Data>::result_type
(BOOST_PP_ENUM_PARAMS(N, A))
>::template impl<Expr, State, Data>
{};
};
#undef N
#endif

View File

@@ -0,0 +1,453 @@
#ifndef BOOST_PP_IS_ITERATING
///////////////////////////////////////////////////////////////////////////////
/// \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/proto/detail/prefix.hpp>
#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/aux_/has_type.hpp>
#include <boost/mpl/aux_/template_arity.hpp>
#include <boost/mpl/aux_/lambda_arity_param.hpp>
#include <boost/utility/result_of.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/remove_reference.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/detail/as_lvalue.hpp>
#include <boost/proto/detail/ignore_unused.hpp>
#include <boost/proto/detail/suffix.hpp>
namespace boost { namespace proto
{
namespace detail
{
template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PROTO_MAX_ARITY, typename A, void)>
struct typelist
{
typedef void type;
};
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, typename Args, typename Void = void>
struct nested_type_if
: nested_type<T>
{};
template<typename R, typename Expr, typename State, typename Data
, bool IsTransform = is_callable<R>::value
>
struct make_if_;
template<typename R, typename Expr, typename State, typename Data
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(long Arity = mpl::aux::template_arity<R>::value)
>
struct make_
{
typedef R type;
typedef void not_applied_;
};
template<typename R, typename Expr, typename State, typename Data>
struct make_if_<R, Expr, State, Data, false>
: make_<R, Expr, State, Data>
{};
#if BOOST_WORKAROUND(__GNUC__, == 3) || (__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;
typedef void not_applied_;
};
#endif
// TODO could optimize this if R is a transform
template<typename R, typename Expr, typename State, typename Data>
struct make_if_<R, Expr, State, Data, true>
: remove_const<typename remove_reference<
typename boost::result_of<R(Expr, State, Data)>::type
>::type>
{};
template<typename Type, bool IsAggregate = is_aggregate<Type>::value>
struct construct_
{
typedef Type result_type;
Type operator ()() const
{
return Type();
}
#define TMP(Z, N, DATA) \
template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \
Type operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a)) const \
{ \
return Type(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), TMP, ~)
#undef TMP
};
template<typename Type>
struct construct_<Type, true>
{
typedef Type result_type;
Type operator ()() const
{
return Type();
}
#define TMP(Z, N, DATA) \
template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \
Type operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a)) const \
{ \
Type that = {BOOST_PP_ENUM_PARAMS_Z(Z, N, a)}; \
return that; \
}
BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), TMP, ~)
#undef TMP
};
#define TMP(Z, N, DATA) \
template<typename Type BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, typename A)> \
Type construct(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a)) \
{ \
return construct_<Type>()(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \
}
BOOST_PP_REPEAT(BOOST_PROTO_MAX_ARITY, TMP, ~)
#undef TMP
}
/// \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>make\<T\<X0,X1,...\> \>::::result\<void(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>make\<U\<Y0,Y1,...\> \>::::result\<void(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>when\<_, X\>::::result\<void(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>
result_type operator ()(
typename impl::expr_param
, typename impl::state_param
, typename impl::data_param
) const
{
return result_type();
}
};
};
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PROTO_MAX_ARITY, <boost/proto/transform/make.hpp>))
#include BOOST_PP_ITERATE()
/// INTERNAL ONLY
///
template<typename Object>
struct is_callable<make<Object> >
: mpl::true_
{};
/// INTERNAL ONLY
///
template<typename PrimitiveTransform>
struct is_callable<protect<PrimitiveTransform> >
: mpl::true_
{};
}}
#endif
#else
#define N BOOST_PP_ITERATION()
namespace detail
{
#if N > 0
template<typename T BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
struct nested_type_if<
T
, typelist<BOOST_PP_ENUM_PARAMS(N, A)>
, typename typelist<
BOOST_PP_ENUM_BINARY_PARAMS(N, typename A, ::not_applied_ BOOST_PP_INTERCEPT)
>::type
>
{
typedef T type;
typedef void not_applied_;
};
#define TMP0(Z, M, DATA) make_if_<BOOST_PP_CAT(A, M), Expr, State, Data>
#define TMP1(Z, M, DATA) typename TMP0(Z, M, DATA) ::type
template<
template<BOOST_PP_ENUM_PARAMS(N, typename BOOST_PP_INTERCEPT)> class R
BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
, typename Expr, typename State, typename Data
>
struct make_<R<BOOST_PP_ENUM_PARAMS(N, A)>, Expr, State, Data
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(N)
>
: nested_type_if<
R<BOOST_PP_ENUM(N, TMP1, ~)>
, typelist<BOOST_PP_ENUM(N, TMP0, ~) >
>
{};
template<
template<BOOST_PP_ENUM_PARAMS(N, typename BOOST_PP_INTERCEPT)> class R
BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
, typename Expr, typename State, typename Data
>
struct make_<noinvoke<R<BOOST_PP_ENUM_PARAMS(N, A)> >, Expr, State, Data
BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(N)
>
{
typedef R<BOOST_PP_ENUM(N, TMP1, ~)> type;
};
#undef TMP0
#undef TMP1
#endif
template<
typename R
BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
, typename Expr, typename State, typename Data
>
struct make_if_<R(BOOST_PP_ENUM_PARAMS(N, A)), Expr, State, Data, false>
{
typedef
typename remove_const<
typename remove_reference<
typename when<_, R(BOOST_PP_ENUM_PARAMS(N, A))>
::template impl<Expr, State, Data>::result_type
>::type
>::type
type;
};
template<
typename R
BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
, typename Expr, typename State, typename Data
>
struct make_if_<R(*)(BOOST_PP_ENUM_PARAMS(N, A)), Expr, State, Data, false>
{
typedef
typename remove_const<
typename remove_reference<
typename when<_, R(BOOST_PP_ENUM_PARAMS(N, A))>
::template impl<Expr, State, Data>::result_type
>::type
>::type
type;
};
template<typename T, typename A>
struct construct_<proto::expr<T, A, N>, true>
{
typedef proto::expr<T, A, N> result_type;
template<BOOST_PP_ENUM_PARAMS(BOOST_PP_MAX(N, 1), typename A)>
result_type operator ()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_MAX(N, 1), A, &a)) const
{
return result_type::make(BOOST_PP_ENUM_PARAMS(BOOST_PP_MAX(N, 1), a));
}
};
}
/// \brief A PrimitiveTransform which computes a type by evaluating any
/// nested transforms and then constructs an object of that type with the
/// current expression, state and data, transformed according
/// to \c A0 through \c AN.
template<typename Object BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
struct make<Object(BOOST_PP_ENUM_PARAMS(N, A))>
: transform<make<Object(BOOST_PP_ENUM_PARAMS(N, A))> >
{
template<typename Expr, typename State, typename Data>
struct impl : transform_impl<Expr, State, Data>
{
/// \brief <tt>make\<Object\>::::result\<void(Expr, State, Data)\>::::type</tt>
typedef typename detail::make_if_<Object, Expr, State, Data>::type result_type;
//typedef typename detail::make_<Object, Expr, State, Data>::type result_type;
/// Let \c ax be <tt>when\<_, Ax\>()(e, s, d)</tt>
/// for each \c x in <tt>[0,N]</tt>.
/// Let \c T be <tt>result\<void(Expr, State, Data)\>::::type</tt>.
/// Return <tt>T(a0, a1,... aN)</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
{
proto::detail::ignore_unused(e);
proto::detail::ignore_unused(s);
proto::detail::ignore_unused(d);
return detail::construct<result_type>(
#define TMP(Z, M, DATA) \
detail::as_lvalue( \
typename when<_, BOOST_PP_CAT(A, M)> \
::template impl<Expr, State, Data>()(e, s, d) \
)
BOOST_PP_ENUM(N, TMP, DATA)
#undef TMP
);
}
};
};
#if BOOST_WORKAROUND(__GNUC__, == 3) || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
// work around GCC bug
template<typename Tag, typename Args, long Arity BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
struct make<proto::expr<Tag, Args, Arity>(BOOST_PP_ENUM_PARAMS(N, A))>
: transform<make<proto::expr<Tag, Args, Arity>(BOOST_PP_ENUM_PARAMS(N, A))> >
{
template<typename Expr, typename State, typename Data>
struct impl : transform_impl<Expr, State, Data>
{
typedef proto::expr<Tag, Args, Arity> result_type;
result_type operator ()(
typename impl::expr_param e
, typename impl::state_param s
, typename impl::data_param d
) const
{
return proto::expr<Tag, Args, Arity>::make(
#define TMP(Z, M, DATA) \
detail::as_lvalue( \
typename when<_, BOOST_PP_CAT(A, M)> \
::template impl<Expr, State, Data>()(e, s, d) \
)
BOOST_PP_ENUM(N, TMP, DATA)
#undef TMP
);
}
};
};
#endif
#undef N
#endif

View File

@@ -0,0 +1,196 @@
#ifndef BOOST_PP_IS_ITERATING
///////////////////////////////////////////////////////////////////////////////
/// \file pass_through.hpp
///
/// Definition of the pass_through transform, which is the default transform
/// of all of the expression generator metafunctions such as unary_plus<>, plus<>
/// and nary_expr<>.
//
// 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_PASS_THROUGH_HPP_EAN_12_26_2006
#define BOOST_PROTO_TRANSFORM_PASS_THROUGH_HPP_EAN_12_26_2006
#include <boost/proto/detail/prefix.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/proto/proto_fwd.hpp>
#include <boost/proto/args.hpp>
#include <boost/proto/transform/impl.hpp>
#include <boost/proto/detail/suffix.hpp>
namespace boost { namespace proto
{
namespace detail
{
template<
typename Grammar
, typename Expr
, typename State
, typename Data
, long Arity = arity_of<Expr>::value
>
struct pass_through_impl
{};
#define BOOST_PROTO_DEFINE_TRANSFORM_TYPE(Z, N, DATA) \
typename Grammar::BOOST_PP_CAT(proto_child, N)::template impl< \
typename result_of::child_c<Expr, N>::type \
, State \
, Data \
>::result_type
#define BOOST_PROTO_DEFINE_TRANSFORM(Z, N, DATA) \
typename Grammar::BOOST_PP_CAT(proto_child, N)::template impl< \
typename result_of::child_c<Expr, N>::type \
, State \
, Data \
>()( \
e.proto_base().BOOST_PP_CAT(child, N), s, d \
)
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PROTO_MAX_ARITY, <boost/proto/transform/pass_through.hpp>))
#include BOOST_PP_ITERATE()
#undef BOOST_PROTO_DEFINE_TRANSFORM
#undef BOOST_PROTO_DEFINE_TRANSFORM_TYPE
template<typename Grammar, typename Expr, typename State, typename Data>
struct pass_through_impl<Grammar, Expr, State, Data, 0>
: transform_impl<Expr, State, Data>
{
typedef Expr result_type;
/// \param e An expression
/// \return \c e
/// \throw nothrow
#ifdef BOOST_HAS_DECLTYPE
result_type
#else
typename pass_through_impl::expr_param
#endif
operator()(
typename pass_through_impl::expr_param e
, typename pass_through_impl::state_param
, typename pass_through_impl::data_param
) const
{
return e;
}
};
} // namespace detail
/// \brief A PrimitiveTransform that transforms the child expressions
/// of an expression node according to the corresponding children of
/// a Grammar.
///
/// Given a Grammar such as <tt>plus\<T0, T1\></tt>, an expression type
/// that matches the grammar such as <tt>plus\<E0, E1\>::::type</tt>, a
/// state \c S and a data \c V, the result of applying the
/// <tt>pass_through\<plus\<T0, T1\> \></tt> transform is:
///
/// \code
/// plus<
/// T0::result<void(E0, S, V)>::type
/// , T1::result<void(E1, S, V)>::type
/// >::type
/// \endcode
///
/// The above demonstrates how child transforms and child expressions
/// are applied pairwise, and how the results are reassembled into a new
/// expression node with the same tag type as the original.
///
/// The explicit use of <tt>pass_through\<\></tt> is not usually needed,
/// since the expression generator metafunctions such as
/// <tt>plus\<\></tt> have <tt>pass_through\<\></tt> as their default
/// transform. So, for instance, these are equivalent:
///
/// \code
/// // Within a grammar definition, these are equivalent:
/// when< plus<X, Y>, pass_through< plus<X, Y> > >
/// when< plus<X, Y>, plus<X, Y> >
/// when< plus<X, Y> > // because of when<class X, class Y=X>
/// plus<X, Y> // because plus<> is both a
/// // grammar and a transform
/// \endcode
///
/// For example, consider the following transform that promotes all
/// \c float terminals in an expression to \c double.
///
/// \code
/// // This transform finds all float terminals in an expression and promotes
/// // them to doubles.
/// struct Promote
/// : or_<
/// when<terminal<float>, terminal<double>::type(_value) >
/// // terminal<>'s default transform is a no-op:
/// , terminal<_>
/// // nary_expr<> has a pass_through<> transform:
/// , nary_expr<_, vararg<Promote> >
/// >
/// {};
/// \endcode
template<typename Grammar>
struct pass_through
: transform<pass_through<Grammar> >
{
template<typename Expr, typename State, typename Data>
struct impl
: detail::pass_through_impl<Grammar, Expr, State, Data>
{};
};
/// INTERNAL ONLY
///
template<typename Grammar>
struct is_callable<pass_through<Grammar> >
: mpl::true_
{};
}} // namespace boost::proto
#endif
#else
#define N BOOST_PP_ITERATION()
template<typename Grammar, typename Expr, typename State, typename Data>
struct pass_through_impl<Grammar, Expr, State, Data, N>
: transform_impl<Expr, State, Data>
{
typedef proto::expr<
typename remove_reference<Expr>::type::proto_tag
, BOOST_PP_CAT(list, N)<
BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_TRANSFORM_TYPE, ~)
>
> result_type;
result_type operator ()(
typename pass_through_impl::expr_param e
, typename pass_through_impl::state_param s
, typename pass_through_impl::data_param d
) const
{
result_type that = {
BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_TRANSFORM, ~)
};
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400))
// Without this, MSVC complains that "that" is uninitialized,
// and it actually triggers a runtime check in debug mode when
// built with VC8.
&that;
#endif
return that;
}
};
#undef N
#endif

View File

@@ -0,0 +1,189 @@
#ifndef BOOST_PP_IS_ITERATING
///////////////////////////////////////////////////////////////////////////////
/// \file when.hpp
/// Definition of when 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_WHEN_HPP_EAN_10_29_2007
#define BOOST_PROTO_TRANSFORM_WHEN_HPP_EAN_10_29_2007
#include <boost/proto/detail/prefix.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/mpl/if.hpp>
#include <boost/proto/proto_fwd.hpp>
#include <boost/proto/traits.hpp>
#include <boost/proto/transform/call.hpp>
#include <boost/proto/transform/make.hpp>
#include <boost/proto/transform/impl.hpp>
#include <boost/proto/detail/suffix.hpp>
namespace boost { namespace proto
{
/// \brief A grammar element and a PrimitiveTransform that associates
/// a transform with the grammar.
///
/// Use <tt>when\<\></tt> to override a grammar's default transform
/// with a custom transform. It is for used when composing larger
/// transforms by associating smaller transforms with individual
/// rules in your grammar, as in the following transform which
/// counts the number of terminals in an expression.
///
/// \code
/// // Count the terminals in an expression tree.
/// // Must be invoked with initial state == mpl::int_<0>().
/// struct CountLeaves
/// : or_<
/// when<terminal<_>, mpl::next<_state>()>
/// , otherwise<fold<_, _state, CountLeaves> >
/// >
/// {};
/// \endcode
///
/// In <tt>when\<G, T\></tt>, when \c T is a class type it is a
/// PrimitiveTransform and the following equivalencies hold:
///
/// <tt>when\<G,T\>::::result\<void(E,S,V)\>::::type</tt> is the same as
/// <tt>T::result\<void(E,S,V)\>::::type</tt>.
///
/// <tt>when\<G,T\>()(e,s,v)</tt> is the same as
/// <tt>T()(e,s,v)</tt>.
template<typename Grammar, typename PrimitiveTransform BOOST_PROTO_WHEN_BUILDING_DOCS(= Grammar)>
struct when
: PrimitiveTransform
{
typedef typename Grammar::proto_base_expr proto_base_expr;
};
/// \brief A specialization that treats function pointer Transforms as
/// if they were function type Transforms.
///
/// This specialization requires that \c Fun is actually a function type.
///
/// This specialization is required for nested transforms such as
/// <tt>when\<G, T0(T1(_))\></tt>. In C++, functions that are used as
/// parameters to other functions automatically decay to funtion
/// pointer types. In other words, the type <tt>T0(T1(_))</tt> is
/// indistinguishable from <tt>T0(T1(*)(_))</tt>. This specialization
/// is required to handle these nested function pointer type transforms
/// properly.
template<typename Grammar, typename Fun>
struct when<Grammar, Fun *>
: when<Grammar, Fun>
{};
/// \brief Syntactic sugar for <tt>when\<_, Fun\></tt>, for use
/// in grammars to handle all the cases not yet handled.
///
/// Use <tt>otherwise\<T\></tt> in your grammars as a synonym for
/// <tt>when\<_, T\></tt> as in the following transform which
/// counts the number of terminals in an expression.
///
/// \code
/// // Count the terminals in an expression tree.
/// // Must be invoked with initial state == mpl::int_<0>().
/// struct CountLeaves
/// : or_<
/// when<terminal<_>, mpl::next<_state>()>
/// , otherwise<fold<_, _state, CountLeaves> >
/// >
/// {};
/// \endcode
template<typename Fun>
struct otherwise
: when<_, Fun>
{};
#define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PROTO_MAX_ARITY, <boost/proto/transform/when.hpp>))
#include BOOST_PP_ITERATE()
}} // namespace boost::proto
#endif
#else
#define N BOOST_PP_ITERATION()
/// \brief A grammar element and a PrimitiveTransform that associates
/// a transform with the grammar.
///
/// Use <tt>when\<\></tt> to override a grammar's default transform
/// with a custom transform. It is for used when composing larger
/// transforms by associating smaller transforms with individual
/// rules in your grammar, as in the following transform which
/// counts the number of terminals in an expression.
///
/// \code
/// // Count the terminals in an expression tree.
/// // Must be invoked with initial state == mpl::int_<0>().
/// struct CountLeaves
/// : or_<
/// when<terminal<_>, mpl::next<_state>()>
/// , otherwise<fold<_, _state, CountLeaves> >
/// >
/// {};
/// \endcode
///
/// The <tt>when\<G, R(A0,A1,...)\></tt> form accepts either a
/// CallableTransform or an ObjectTransform as its second parameter.
/// <tt>when\<\></tt> uses <tt>is_callable\<R\>::::value</tt> to
/// distinguish between the two, and uses <tt>call\<\></tt> to
/// evaluate CallableTransforms and <tt>make\<\></tt> to evaluate
/// ObjectTransforms.
template<typename Grammar, typename R BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
struct when<Grammar, R(BOOST_PP_ENUM_PARAMS(N, A))>
: transform<when<Grammar, R(BOOST_PP_ENUM_PARAMS(N, A))> >
{
typedef typename Grammar::proto_base_expr proto_base_expr;
// Note: do not evaluate is_callable<R> in this scope.
// R may be an incomplete type at this point.
template<typename Expr, typename State, typename Data>
struct impl : transform_impl<Expr, State, Data>
{
typedef call<R(BOOST_PP_ENUM_PARAMS(N, A))> call_;
typedef make<R(BOOST_PP_ENUM_PARAMS(N, A))> make_;
typedef
typename mpl::if_c<
// OK to evaluate is_callable<R> here.
// R should be compete by now.
is_callable<R>::value
, call_ // "R" is a function to call
, make_ // "R" is an object to construct
>::type
which;
typedef typename which::template impl<Expr, State, Data>::result_type result_type;
/// Evaluate <tt>R(A0,A1,...)</tt> as a transform either with
/// <tt>call\<\></tt> or with <tt>make\<\></tt> depending on
/// whether <tt>is_callable\<R\>::::value</tt> is \c true or
/// \c false.
///
/// \param e The current expression
/// \param s The current state
/// \param d An arbitrary data
/// \pre <tt>matches\<Expr, Grammar\>::::value</tt> is \c true
/// \return <tt>result\<void(Expr, State, Data)\>::::impl()(e, s, d)</tt>
result_type operator ()(
typename impl::expr_param e
, typename impl::state_param s
, typename impl::data_param d
) const
{
return typename which::template impl<Expr, State, Data>()(e, s, d);
}
};
};
#undef N
#endif