1725 lines
63 KiB
C++
1725 lines
63 KiB
C++
#ifndef BOOST_PP_IS_ITERATING
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// 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)
|
|
//
|
|
// This example contains a full-featured reimplementation of the old,
|
|
// now-deprecated Boost Lambda Library (BLL) on top of Boost.Proto. It
|
|
// is necessarily complex to accomodate all the quirks and inconsistencies
|
|
// of that old library, but it is a good example of how to build a
|
|
// complete and full-featured EDLS using Proto.
|
|
#ifndef BOOST_LAMBDA_HPP_EAN_04_19_2008
|
|
#define BOOST_LAMBDA_HPP_EAN_04_19_2008
|
|
|
|
#include <iosfwd>
|
|
#include <typeinfo>
|
|
#include <algorithm>
|
|
#include <boost/ref.hpp>
|
|
#include <boost/assert.hpp>
|
|
#include <boost/mpl/or.hpp>
|
|
#include <boost/mpl/int.hpp>
|
|
#include <boost/mpl/void.hpp>
|
|
#include <boost/mpl/identity.hpp>
|
|
#include <boost/mpl/next_prior.hpp>
|
|
#include <boost/mpl/min_max.hpp>
|
|
#include <boost/mpl/assert.hpp>
|
|
#include <boost/preprocessor.hpp>
|
|
#include <boost/utility/enable_if.hpp>
|
|
#include <boost/utility/result_of.hpp>
|
|
#include <boost/fusion/include/vector.hpp>
|
|
#include <boost/type_traits/add_reference.hpp>
|
|
#include <boost/type_traits/remove_reference.hpp>
|
|
#include <boost/type_traits/remove_const.hpp>
|
|
#include <boost/type_traits/is_same.hpp>
|
|
#include <boost/proto/proto.hpp>
|
|
|
|
#ifndef BOOST_LAMBDA_MAX_ARITY
|
|
# define BOOST_LAMBDA_MAX_ARITY 3
|
|
#endif
|
|
|
|
#ifdef _MSC_VER
|
|
# pragma warning(push)
|
|
# pragma warning(disable: 4355) // 'this' : used in base member initializer list
|
|
# pragma warning(disable: 4065) // switch statement contains 'default' but no 'case' labels
|
|
#endif
|
|
|
|
namespace boost { namespace lambda
|
|
{
|
|
namespace tag
|
|
{
|
|
struct if_ {};
|
|
struct if_else_ {};
|
|
struct for_ {};
|
|
struct while_ {};
|
|
struct do_while_ {};
|
|
struct protect {};
|
|
struct try_ {};
|
|
struct throw_ {};
|
|
struct rethrow_ {};
|
|
struct switch_ {};
|
|
struct default_ {};
|
|
template<int I> struct case_ { static const int value = I; };
|
|
template<typename E> struct catch_ { typedef E exception_type; };
|
|
struct catch_all_ { typedef catch_all_ exception_type; };
|
|
};
|
|
|
|
template<typename Int>
|
|
struct placeholder
|
|
{
|
|
typedef typename Int::tag tag;
|
|
typedef typename Int::value_type value_type;
|
|
typedef placeholder<Int> type;
|
|
typedef placeholder<typename Int::next> next;
|
|
typedef placeholder<typename Int::prior> prior;
|
|
static const value_type value = Int::value;
|
|
|
|
friend std::ostream &operator<<(std::ostream &sout, placeholder)
|
|
{
|
|
return sout << "boost::lambda::_" << (Int::value+1);
|
|
}
|
|
};
|
|
|
|
struct exception_placeholder
|
|
{};
|
|
|
|
struct no_exception_type {};
|
|
no_exception_type const no_exception = {};
|
|
|
|
// Calculate the arity of a lambda expression
|
|
struct Arity
|
|
: proto::or_<
|
|
proto::when<proto::terminal<placeholder<proto::_> >, mpl::next<proto::_value>()>
|
|
, proto::when<proto::terminal<proto::_>, mpl::int_<0>()>
|
|
, proto::otherwise<proto::fold<proto::_, mpl::int_<0>(), mpl::max<proto::_state, Arity>()> >
|
|
>
|
|
{};
|
|
|
|
// True when a lambda expression can be applied with no arguments and
|
|
// without an active exception object
|
|
struct IsNullary
|
|
: proto::or_<
|
|
proto::when<proto::terminal<placeholder<proto::_> >, mpl::false_()>
|
|
, proto::when<proto::terminal<exception_placeholder>, mpl::false_()>
|
|
, proto::when<proto::terminal<proto::_>, mpl::true_()>
|
|
, proto::otherwise<proto::fold<proto::_, mpl::true_(), mpl::and_<proto::_state, IsNullary>()> >
|
|
>
|
|
{};
|
|
|
|
struct Eval;
|
|
|
|
struct EvalWhile : proto::transform<EvalWhile>
|
|
{
|
|
template<typename Expr, typename State, typename Data>
|
|
struct impl : proto::transform_impl<Expr, State, Data>
|
|
{
|
|
typedef mpl::void_ result_type;
|
|
|
|
result_type operator()(
|
|
typename impl::expr_param expr
|
|
, typename impl::state_param state
|
|
, typename impl::data_param data
|
|
) const
|
|
{
|
|
while(Eval()(proto::left(expr), state, data))
|
|
{
|
|
Eval()(proto::right(expr), state, data);
|
|
}
|
|
return result_type();
|
|
}
|
|
};
|
|
};
|
|
|
|
struct EvalDoWhile : proto::transform<EvalDoWhile>
|
|
{
|
|
template<typename Expr, typename State, typename Data>
|
|
struct impl : proto::transform_impl<Expr, State, Data>
|
|
{
|
|
typedef mpl::void_ result_type;
|
|
|
|
result_type operator()(
|
|
typename impl::expr_param expr
|
|
, typename impl::state_param state
|
|
, typename impl::data_param data
|
|
) const
|
|
{
|
|
do
|
|
{
|
|
Eval()(proto::child_c<0>(expr), state, data);
|
|
}
|
|
while(Eval()(proto::child_c<1>(expr), state, data));
|
|
|
|
return result_type();
|
|
}
|
|
};
|
|
};
|
|
|
|
struct EvalFor : proto::transform<EvalFor>
|
|
{
|
|
template<typename Expr, typename State, typename Data>
|
|
struct impl : proto::transform_impl<Expr, State, Data>
|
|
{
|
|
typedef mpl::void_ result_type;
|
|
|
|
result_type operator()(
|
|
typename impl::expr_param expr
|
|
, typename impl::state_param state
|
|
, typename impl::data_param data
|
|
) const
|
|
{
|
|
for(Eval()(proto::child_c<0>(expr), state, data)
|
|
; Eval()(proto::child_c<1>(expr), state, data)
|
|
; Eval()(proto::child_c<2>(expr), state, data))
|
|
{
|
|
Eval()(proto::child_c<3>(expr), state, data);
|
|
}
|
|
return result_type();
|
|
}
|
|
};
|
|
};
|
|
|
|
struct EvalIf : proto::transform<EvalIf>
|
|
{
|
|
template<typename Expr, typename State, typename Data>
|
|
struct impl : proto::transform_impl<Expr, State, Data>
|
|
{
|
|
typedef mpl::void_ result_type;
|
|
|
|
result_type operator()(
|
|
typename impl::expr_param expr
|
|
, typename impl::state_param state
|
|
, typename impl::data_param data
|
|
) const
|
|
{
|
|
if(Eval()(proto::left(expr), state, data))
|
|
{
|
|
Eval()(proto::right(expr), state, data);
|
|
}
|
|
return result_type();
|
|
}
|
|
};
|
|
};
|
|
|
|
struct EvalIfElse : proto::transform<EvalIfElse>
|
|
{
|
|
template<typename Expr, typename State, typename Data>
|
|
struct impl : proto::transform_impl<Expr, State, Data>
|
|
{
|
|
typedef mpl::void_ result_type;
|
|
|
|
result_type operator()(
|
|
typename impl::expr_param expr
|
|
, typename impl::state_param state
|
|
, typename impl::data_param data
|
|
) const
|
|
{
|
|
if(Eval()(proto::child_c<0>(expr), state, data))
|
|
{
|
|
Eval()(proto::child_c<1>(expr), state, data);
|
|
}
|
|
else
|
|
{
|
|
Eval()(proto::child_c<2>(expr), state, data);
|
|
}
|
|
return result_type();
|
|
}
|
|
};
|
|
};
|
|
|
|
struct EvalException : proto::transform<EvalException>
|
|
{
|
|
template<typename Expr, typename State, typename Data>
|
|
struct impl : proto::transform_impl<Expr, State, Data>
|
|
{
|
|
typedef typename remove_const<typename impl::state>::type result_type;
|
|
BOOST_MPL_ASSERT_NOT((is_same<result_type, no_exception_type>));
|
|
BOOST_MPL_ASSERT_NOT((is_same<result_type, tag::catch_all_>));
|
|
|
|
typename impl::state_param operator()(
|
|
typename impl::expr_param
|
|
, typename impl::state_param state
|
|
, typename impl::data_param
|
|
) const
|
|
{
|
|
return state;
|
|
}
|
|
};
|
|
};
|
|
|
|
struct EvalSwitch : proto::transform<EvalSwitch>
|
|
{
|
|
template<typename Expr, typename State, typename Data, long Arity, typename BackTag>
|
|
struct impl2;
|
|
|
|
#define M0(Z, N, DATA) \
|
|
case proto::tag_of<typename proto::result_of::child_c<Expr, N>::type>::type::value: \
|
|
Eval()(proto::child_c<N>(expr), state, data); \
|
|
break; \
|
|
/**/
|
|
|
|
#define M1(Z, N, DATA) \
|
|
template<typename Expr, typename State, typename Data, typename BackTag> \
|
|
struct impl2<Expr, State, Data, N, BackTag> \
|
|
: proto::transform_impl<Expr, State, Data> \
|
|
{ \
|
|
typedef void result_type; \
|
|
\
|
|
void operator()( \
|
|
typename impl2::expr_param expr \
|
|
, typename impl2::state_param state \
|
|
, typename impl2::data_param data \
|
|
) const \
|
|
{ \
|
|
switch(Eval()(proto::child_c<0>(expr), state, data)) \
|
|
{ \
|
|
BOOST_PP_REPEAT_FROM_TO_ ## Z(1, N, M0, ~) \
|
|
default: \
|
|
break; \
|
|
} \
|
|
} \
|
|
}; \
|
|
\
|
|
template<typename Expr, typename State, typename Data> \
|
|
struct impl2<Expr, State, Data, N, tag::default_> \
|
|
: proto::transform_impl<Expr, State, Data> \
|
|
{ \
|
|
typedef void result_type; \
|
|
\
|
|
void operator()( \
|
|
typename impl2::expr_param expr \
|
|
, typename impl2::state_param state \
|
|
, typename impl2::data_param data \
|
|
) const \
|
|
{ \
|
|
switch(Eval()(proto::child_c<0>(expr), state, data)) \
|
|
{ \
|
|
BOOST_PP_REPEAT_FROM_TO_ ## Z(1, BOOST_PP_DEC(N), M0, ~) \
|
|
default:; \
|
|
Eval()(proto::child_c<BOOST_PP_DEC(N)>(expr), state, data); \
|
|
break; \
|
|
} \
|
|
} \
|
|
}; \
|
|
/**/
|
|
BOOST_PP_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1, ~)
|
|
#undef M0
|
|
#undef M1
|
|
|
|
template<typename Expr, typename State, typename Data>
|
|
struct impl
|
|
: impl2<
|
|
Expr
|
|
, State
|
|
, Data
|
|
, proto::arity_of<Expr>::value
|
|
, typename proto::tag_of<
|
|
typename proto::result_of::child_c<
|
|
Expr
|
|
, proto::arity_of<Expr>::value-1
|
|
>::type
|
|
>::type
|
|
>
|
|
{};
|
|
};
|
|
|
|
struct throw_fun
|
|
{
|
|
BOOST_PROTO_CALLABLE()
|
|
typedef void result_type;
|
|
template<typename Expr>
|
|
void operator()(Expr const &e) const
|
|
{
|
|
throw e;
|
|
}
|
|
};
|
|
|
|
struct unwrap_ref : proto::callable
|
|
{
|
|
template<typename Sig>
|
|
struct result;
|
|
|
|
template<typename This, typename T>
|
|
struct result<This(reference_wrapper<T>)>
|
|
{
|
|
typedef T &type;
|
|
};
|
|
|
|
template<typename This, typename T>
|
|
struct result<This(T &)>
|
|
: result<This(T)>
|
|
{};
|
|
|
|
template<typename T>
|
|
T &operator()(reference_wrapper<T> const &ref) const
|
|
{
|
|
return ref;
|
|
}
|
|
};
|
|
|
|
struct anytype
|
|
{
|
|
template<typename T>
|
|
anytype(T &) { BOOST_ASSERT(false); }
|
|
template<typename T>
|
|
operator T &() const { BOOST_ASSERT(false); throw; }
|
|
private:
|
|
anytype();
|
|
};
|
|
|
|
struct rethrow_fun
|
|
{
|
|
BOOST_PROTO_CALLABLE()
|
|
typedef anytype result_type;
|
|
template<typename State>
|
|
anytype operator()(State const &) const
|
|
{
|
|
BOOST_MPL_ASSERT_NOT((is_same<State, no_exception_type>));
|
|
throw;
|
|
}
|
|
};
|
|
|
|
struct Cases
|
|
{
|
|
template<typename Tag>
|
|
struct case_
|
|
: proto::otherwise<proto::_default<Eval> >
|
|
{};
|
|
|
|
template<typename E>
|
|
struct case_<tag::catch_<E> >
|
|
: proto::otherwise<Eval(proto::_child)>
|
|
{};
|
|
|
|
template<int I>
|
|
struct case_<tag::case_<I> >
|
|
: proto::otherwise<Eval(proto::_child)>
|
|
{};
|
|
};
|
|
|
|
template<> struct Cases::case_<tag::while_> : proto::otherwise<EvalWhile> {};
|
|
template<> struct Cases::case_<tag::for_> : proto::otherwise<EvalFor> {};
|
|
template<> struct Cases::case_<tag::if_> : proto::otherwise<EvalIf> {};
|
|
template<> struct Cases::case_<tag::if_else_> : proto::otherwise<EvalIfElse> {};
|
|
template<> struct Cases::case_<tag::do_while_> : proto::otherwise<EvalDoWhile> {};
|
|
template<> struct Cases::case_<tag::switch_> : proto::otherwise<EvalSwitch> {};
|
|
template<> struct Cases::case_<tag::protect> : proto::otherwise<proto::_child> {};
|
|
template<> struct Cases::case_<tag::default_> : proto::otherwise<Eval(proto::_child)> {};
|
|
template<> struct Cases::case_<tag::catch_all_> : proto::otherwise<Eval(proto::_child)> {};
|
|
|
|
template<>
|
|
struct Cases::case_<proto::tag::terminal>
|
|
: proto::or_<
|
|
proto::when<
|
|
proto::terminal<placeholder<proto::_> >
|
|
, proto::functional::at(proto::_data, proto::_value)
|
|
>
|
|
, proto::when<
|
|
proto::terminal<exception_placeholder>
|
|
, EvalException
|
|
>
|
|
, proto::when<
|
|
proto::terminal<reference_wrapper<proto::_> >
|
|
, unwrap_ref(proto::_value)
|
|
>
|
|
, proto::otherwise<proto::_default<Eval> >
|
|
>
|
|
{};
|
|
|
|
template<>
|
|
struct Cases::case_<proto::tag::function>
|
|
: proto::or_<
|
|
proto::when<
|
|
proto::function<proto::terminal<rethrow_fun> >
|
|
, rethrow_fun(proto::_state)
|
|
>
|
|
, proto::otherwise<proto::_default<Eval> >
|
|
>
|
|
{};
|
|
|
|
struct Eval
|
|
: proto::switch_<Cases>
|
|
{};
|
|
|
|
// Use a grammar to disable Proto's assignment operator overloads.
|
|
// We'll define our own because we want (x+=_1) to store x by
|
|
// reference. (In all other cases, variables are stored by value
|
|
// within lambda expressions.)
|
|
struct Grammar
|
|
: proto::switch_<struct AssignOps>
|
|
{};
|
|
|
|
struct AssignOps
|
|
{
|
|
template<typename Tag> struct case_ : proto::_ {};
|
|
};
|
|
|
|
template<> struct AssignOps::case_<proto::tag::shift_left_assign> : proto::not_<proto::_> {};
|
|
template<> struct AssignOps::case_<proto::tag::shift_right_assign> : proto::not_<proto::_> {};
|
|
template<> struct AssignOps::case_<proto::tag::multiplies_assign> : proto::not_<proto::_> {};
|
|
template<> struct AssignOps::case_<proto::tag::divides_assign> : proto::not_<proto::_> {};
|
|
template<> struct AssignOps::case_<proto::tag::modulus_assign> : proto::not_<proto::_> {};
|
|
template<> struct AssignOps::case_<proto::tag::plus_assign> : proto::not_<proto::_> {};
|
|
template<> struct AssignOps::case_<proto::tag::minus_assign> : proto::not_<proto::_> {};
|
|
template<> struct AssignOps::case_<proto::tag::bitwise_and_assign> : proto::not_<proto::_> {};
|
|
template<> struct AssignOps::case_<proto::tag::bitwise_or_assign> : proto::not_<proto::_> {};
|
|
template<> struct AssignOps::case_<proto::tag::bitwise_xor_assign> : proto::not_<proto::_> {};
|
|
|
|
namespace exprns_
|
|
{
|
|
template<typename Expr>
|
|
struct llexpr;
|
|
}
|
|
|
|
using exprns_::llexpr;
|
|
|
|
// Wrap expressions in lambda::llexpr<>.
|
|
struct Generator
|
|
: proto::pod_generator<llexpr>
|
|
{};
|
|
|
|
// The domain for the lambda library.
|
|
struct lldomain
|
|
: proto::domain<Generator, Grammar, proto::default_domain>
|
|
{
|
|
// Make all terminals and children held by value instead of by reference.
|
|
// Proto::domain<>::as_expr<> holds everything it can by value; the only
|
|
// exceptions are function types, abstract types, and iostreams.
|
|
template<typename T>
|
|
struct as_child
|
|
: proto_base_domain::as_expr<T>
|
|
{};
|
|
|
|
// The exception is arrays, which should still be held by reference
|
|
template<typename T, std::size_t N>
|
|
struct as_child<T[N]>
|
|
: proto_base_domain::as_child<T[N]>
|
|
{};
|
|
};
|
|
|
|
template<typename Sig>
|
|
struct llresult;
|
|
|
|
template<typename This>
|
|
struct llresult<This()>
|
|
: mpl::if_c<
|
|
result_of<IsNullary(This &)>::type::value
|
|
, result_of<Eval(This &, no_exception_type const &, fusion::vector0<> &)>
|
|
, mpl::identity<void>
|
|
>::type
|
|
{};
|
|
|
|
#define M0(Z, N, DATA) \
|
|
template<typename This BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, typename A)> \
|
|
struct llresult<This(BOOST_PP_ENUM_PARAMS_Z(Z, N, A))> \
|
|
: result_of< \
|
|
Eval( \
|
|
This & \
|
|
, no_exception_type const & \
|
|
, BOOST_PP_CAT(fusion::vector, N)<BOOST_PP_ENUM_PARAMS_Z(Z, N, A)> & \
|
|
) \
|
|
> \
|
|
{}; \
|
|
/**/
|
|
BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_LAMBDA_MAX_ARITY), M0, ~)
|
|
#undef M0
|
|
|
|
template<typename Expr>
|
|
struct llexpr
|
|
{
|
|
BOOST_PROTO_BASIC_EXTENDS(Expr, llexpr<Expr>, lldomain)
|
|
BOOST_PROTO_EXTENDS_ASSIGN()
|
|
BOOST_PROTO_EXTENDS_SUBSCRIPT()
|
|
|
|
template<typename Sig>
|
|
struct result
|
|
: llresult<Sig>
|
|
{};
|
|
|
|
typename result<llexpr const()>::type
|
|
operator()() const
|
|
{
|
|
fusion::vector0<> args;
|
|
return Eval()(*this, no_exception, args);
|
|
}
|
|
|
|
#define M1(Z, N, _) ((0)(1))
|
|
|
|
#define M2(R, PRODUCT) M3(R, BOOST_PP_SEQ_SIZE(PRODUCT), PRODUCT)
|
|
|
|
#define M3(R, SIZE, PRODUCT) \
|
|
template<BOOST_PP_ENUM_PARAMS(SIZE, typename A)> \
|
|
typename result<llexpr const(BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT))>::type \
|
|
operator ()(BOOST_PP_SEQ_FOR_EACH_I_R(R, M4, ~, PRODUCT)) const \
|
|
{ \
|
|
BOOST_MPL_ASSERT_RELATION(result_of<Arity(Expr const &)>::type::value, <=, SIZE); \
|
|
BOOST_PP_CAT(fusion::vector, SIZE)<BOOST_PP_SEQ_FOR_EACH_I_R(R, M5, ~, PRODUCT)> args \
|
|
(BOOST_PP_SEQ_FOR_EACH_I_R(R, M6, ~, PRODUCT)); \
|
|
return Eval()(*this, no_exception, args); \
|
|
} \
|
|
/**/
|
|
|
|
#define M4(R, _, I, ELEM) \
|
|
BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM) &BOOST_PP_CAT(a, I) \
|
|
/**/
|
|
|
|
#define M5(R, _, I, ELEM) \
|
|
BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(A, I) BOOST_PP_CAT(C, ELEM)& \
|
|
/**/
|
|
|
|
#define M6(R, _, I, ELEM) \
|
|
BOOST_PP_COMMA_IF(I) BOOST_PP_CAT(a, I) \
|
|
/**/
|
|
|
|
#define C0
|
|
|
|
#define C1 const
|
|
|
|
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_LAMBDA_MAX_ARITY, "./lambda.hpp"))
|
|
#include BOOST_PP_ITERATE()
|
|
|
|
#undef C0
|
|
#undef C1
|
|
#undef M1
|
|
#undef M2
|
|
#undef M3
|
|
#undef M4
|
|
#undef M5
|
|
#undef M6
|
|
};
|
|
|
|
typedef llexpr<proto::terminal<placeholder<mpl::int_<0> > >::type> placeholder1_type;
|
|
typedef llexpr<proto::terminal<placeholder<mpl::int_<1> > >::type> placeholder2_type;
|
|
typedef llexpr<proto::terminal<placeholder<mpl::int_<2> > >::type> placeholder3_type;
|
|
|
|
placeholder1_type const _1 = {{{}}};
|
|
placeholder2_type const _2 = {{{}}};
|
|
placeholder3_type const _3 = {{{}}};
|
|
|
|
placeholder1_type const free1 = {{{}}};
|
|
placeholder2_type const free2 = {{{}}};
|
|
placeholder3_type const free3 = {{{}}};
|
|
|
|
typedef llexpr<proto::terminal<exception_placeholder>::type> placeholderE_type;
|
|
placeholderE_type const _e = {{{}}};
|
|
|
|
struct byref
|
|
{
|
|
template<typename Sig>
|
|
struct result;
|
|
|
|
template<typename This, typename T>
|
|
struct result<This(T &)>
|
|
{
|
|
typedef llexpr<typename proto::terminal<T &>::type> type;
|
|
};
|
|
|
|
template<typename This, typename T>
|
|
struct result<This(llexpr<T> &)>
|
|
{
|
|
typedef boost::reference_wrapper<llexpr<T> > type;
|
|
};
|
|
|
|
template<typename This, typename T>
|
|
struct result<This(llexpr<T> const &)>
|
|
{
|
|
typedef boost::reference_wrapper<llexpr<T> const> type;
|
|
};
|
|
|
|
template<typename T>
|
|
typename result<byref(T &)>::type operator()(T &t) const
|
|
{
|
|
typename result<byref(T &)>::type that = {{t}};
|
|
return that;
|
|
}
|
|
|
|
template<typename T>
|
|
typename result<byref(T const &)>::type operator()(T const &t) const
|
|
{
|
|
typename result<byref(T const &)>::type that = {{t}};
|
|
return that;
|
|
}
|
|
|
|
template<typename T>
|
|
boost::reference_wrapper<llexpr<T> > operator()(llexpr<T> &t) const
|
|
{
|
|
return boost::ref(t);
|
|
}
|
|
|
|
template<typename T>
|
|
boost::reference_wrapper<llexpr<T> const> operator()(llexpr<T> const &t) const
|
|
{
|
|
return boost::ref(t);
|
|
}
|
|
};
|
|
|
|
namespace exprns_
|
|
{
|
|
// Ugh, the assign operators (and only the assign operators) store
|
|
// their left terminals by reference. That requires this special handling.
|
|
#define BOOST_LAMBDA_DEFINE_ASSIGN_OP(OP, TAG) \
|
|
template<typename T, typename U> \
|
|
typename proto::result_of::make_expr< \
|
|
TAG \
|
|
, lldomain \
|
|
, typename boost::result_of<byref(T &)>::type \
|
|
, U & \
|
|
>::type const \
|
|
operator OP(T &t, U &u) \
|
|
{ \
|
|
return proto::make_expr<TAG, lldomain>(byref()(t), boost::ref(u)); \
|
|
} \
|
|
template<typename T, typename U> \
|
|
typename proto::result_of::make_expr< \
|
|
TAG \
|
|
, lldomain \
|
|
, typename boost::result_of<byref(T &)>::type \
|
|
, U const & \
|
|
>::type const \
|
|
operator OP(T &t, U const &u) \
|
|
{ \
|
|
return proto::make_expr<TAG, lldomain>(byref()(t), boost::ref(u)); \
|
|
} \
|
|
/**/
|
|
|
|
BOOST_LAMBDA_DEFINE_ASSIGN_OP(<<=, boost::proto::tag::shift_left_assign)
|
|
BOOST_LAMBDA_DEFINE_ASSIGN_OP(>>=, boost::proto::tag::shift_right_assign)
|
|
BOOST_LAMBDA_DEFINE_ASSIGN_OP(*= , boost::proto::tag::multiplies_assign)
|
|
BOOST_LAMBDA_DEFINE_ASSIGN_OP(/= , boost::proto::tag::divides_assign)
|
|
BOOST_LAMBDA_DEFINE_ASSIGN_OP(%= , boost::proto::tag::modulus_assign)
|
|
BOOST_LAMBDA_DEFINE_ASSIGN_OP(+= , boost::proto::tag::plus_assign)
|
|
BOOST_LAMBDA_DEFINE_ASSIGN_OP(-= , boost::proto::tag::minus_assign)
|
|
BOOST_LAMBDA_DEFINE_ASSIGN_OP(&= , boost::proto::tag::bitwise_and_assign)
|
|
BOOST_LAMBDA_DEFINE_ASSIGN_OP(|= , boost::proto::tag::bitwise_or_assign)
|
|
BOOST_LAMBDA_DEFINE_ASSIGN_OP(^= , boost::proto::tag::bitwise_xor_assign)
|
|
}
|
|
|
|
template<typename T>
|
|
struct var_type
|
|
{
|
|
typedef llexpr<typename proto::terminal<T &>::type> type;
|
|
};
|
|
|
|
template<typename T>
|
|
llexpr<typename proto::terminal<T &>::type> const
|
|
var(T &t)
|
|
{
|
|
llexpr<typename proto::terminal<T &>::type> that = {{t}};
|
|
return that;
|
|
}
|
|
|
|
template<typename T>
|
|
struct constant_type
|
|
: proto::result_of::make_expr<
|
|
proto::tag::terminal
|
|
, lldomain
|
|
, T const &
|
|
>
|
|
{};
|
|
|
|
template<typename T>
|
|
typename constant_type<T>::type const
|
|
constant(T const &t)
|
|
{
|
|
typename constant_type<T>::type that = {{t}};
|
|
return that;
|
|
}
|
|
|
|
template<typename T>
|
|
struct constant_ref_type
|
|
{
|
|
typedef llexpr<typename proto::terminal<T const &>::type> type;
|
|
};
|
|
|
|
template<typename T>
|
|
llexpr<typename proto::terminal<T const &>::type> const
|
|
constant_ref(T const &t)
|
|
{
|
|
llexpr<typename proto::terminal<T const &>::type> that = {{t}};
|
|
return that;
|
|
}
|
|
|
|
template<typename Cond>
|
|
struct while_generator
|
|
{
|
|
explicit while_generator(Cond const &c)
|
|
: cond(c)
|
|
{}
|
|
|
|
template<typename Body>
|
|
typename proto::result_of::make_expr<
|
|
tag::while_
|
|
, lldomain
|
|
, Cond const &
|
|
, Body const &
|
|
>::type const
|
|
operator[](Body const &body) const
|
|
{
|
|
return proto::make_expr<tag::while_, lldomain>(
|
|
boost::ref(this->cond)
|
|
, boost::ref(body)
|
|
);
|
|
}
|
|
|
|
private:
|
|
Cond const &cond;
|
|
};
|
|
|
|
template<typename Expr>
|
|
while_generator<Expr> while_(Expr const &expr)
|
|
{
|
|
return while_generator<Expr>(expr);
|
|
}
|
|
|
|
template<typename Expr>
|
|
struct else_generator
|
|
{
|
|
typedef typename proto::result_of::left<Expr const &>::type condition_type;
|
|
typedef typename proto::result_of::right<Expr const &>::type body1_type;
|
|
|
|
explicit else_generator(Expr const &expr)
|
|
: if_(expr)
|
|
{}
|
|
|
|
template<typename Body2>
|
|
typename proto::result_of::make_expr<
|
|
tag::if_else_
|
|
, lldomain
|
|
, condition_type
|
|
, body1_type
|
|
, Body2 const &
|
|
>::type const
|
|
operator[](Body2 const &body2) const
|
|
{
|
|
return proto::make_expr<tag::if_else_, lldomain>(
|
|
boost::ref(proto::left(this->if_))
|
|
, boost::ref(proto::right(this->if_))
|
|
, boost::ref(body2)
|
|
);
|
|
}
|
|
|
|
private:
|
|
Expr const &if_;
|
|
};
|
|
|
|
template<typename Expr>
|
|
struct with_else : Expr
|
|
{
|
|
template<typename T>
|
|
with_else(T const &expr)
|
|
: Expr(expr)
|
|
, else_(*this)
|
|
{}
|
|
|
|
else_generator<Expr> else_;
|
|
};
|
|
|
|
template<typename Cond>
|
|
struct if_generator
|
|
{
|
|
explicit if_generator(Cond const &c)
|
|
: cond(c)
|
|
{}
|
|
|
|
template<typename Body>
|
|
with_else<
|
|
typename proto::result_of::make_expr<
|
|
tag::if_
|
|
, lldomain
|
|
, Cond const &
|
|
, Body const &
|
|
>::type
|
|
> const
|
|
operator[](Body const &body) const
|
|
{
|
|
return proto::make_expr<tag::if_, lldomain>(
|
|
boost::ref(this->cond)
|
|
, boost::ref(body)
|
|
);
|
|
}
|
|
|
|
private:
|
|
Cond const &cond;
|
|
};
|
|
|
|
template<typename Expr>
|
|
if_generator<Expr> if_(Expr const &expr)
|
|
{
|
|
return if_generator<Expr>(expr);
|
|
}
|
|
|
|
template<typename Init, typename Cond, typename Oper>
|
|
struct for_generator
|
|
{
|
|
explicit for_generator(Init const &i, Cond const &c, Oper const &o)
|
|
: init(i)
|
|
, cond(c)
|
|
, oper(o)
|
|
{}
|
|
|
|
template<typename Body>
|
|
typename proto::result_of::make_expr<
|
|
tag::for_
|
|
, lldomain
|
|
, Init const &
|
|
, Cond const &
|
|
, Oper const &
|
|
, Body const &
|
|
>::type const
|
|
operator[](Body const &body) const
|
|
{
|
|
return proto::make_expr<tag::for_, lldomain>(
|
|
boost::ref(this->init)
|
|
, boost::ref(this->cond)
|
|
, boost::ref(this->oper)
|
|
, boost::ref(body)
|
|
);
|
|
}
|
|
|
|
private:
|
|
Init const &init;
|
|
Cond const &cond;
|
|
Oper const &oper;
|
|
};
|
|
|
|
template<typename Init, typename Cond, typename Oper>
|
|
for_generator<Init, Cond, Oper> for_(Init const &i, Cond const &c, Oper const &o)
|
|
{
|
|
return for_generator<Init, Cond, Oper>(i, c, o);
|
|
}
|
|
|
|
template<typename Body>
|
|
struct do_while_generator
|
|
{
|
|
explicit do_while_generator(Body const &b)
|
|
: body(b)
|
|
{}
|
|
|
|
template<typename Cond>
|
|
typename proto::result_of::make_expr<
|
|
tag::do_while_
|
|
, lldomain
|
|
, Body const &
|
|
, Cond const &
|
|
>::type const
|
|
operator()(Cond const &cond) const
|
|
{
|
|
return proto::make_expr<tag::do_while_, lldomain>(
|
|
boost::ref(this->body)
|
|
, boost::ref(cond)
|
|
);
|
|
}
|
|
|
|
private:
|
|
Body const &body;
|
|
};
|
|
|
|
template<typename Body>
|
|
struct do_body
|
|
{
|
|
explicit do_body(Body const &body)
|
|
: while_(body)
|
|
{}
|
|
|
|
do_while_generator<Body> while_;
|
|
};
|
|
|
|
struct do_generator
|
|
{
|
|
template<typename Body>
|
|
do_body<Body> operator[](Body const &body) const
|
|
{
|
|
return do_body<Body>(body);
|
|
}
|
|
};
|
|
|
|
do_generator const do_ = {};
|
|
|
|
struct noop_fun
|
|
{
|
|
typedef void result_type;
|
|
void operator()() const {}
|
|
};
|
|
|
|
typedef llexpr<proto::function<llexpr<proto::terminal<noop_fun>::type> >::type> noop_type;
|
|
noop_type const noop = {{{{{}}}}};
|
|
|
|
template<typename Init, typename Cond, typename Oper>
|
|
typename proto::result_of::make_expr<
|
|
tag::for_
|
|
, lldomain
|
|
, Init const &
|
|
, Cond const &
|
|
, Oper const &
|
|
, noop_type const &
|
|
>::type const
|
|
for_loop(Init const &init, Cond const &cond, Oper const &oper)
|
|
{
|
|
return proto::make_expr<tag::for_, lldomain>(
|
|
boost::ref(init)
|
|
, boost::ref(cond)
|
|
, boost::ref(oper)
|
|
, boost::ref(noop)
|
|
);
|
|
}
|
|
|
|
template<typename Init, typename Cond, typename Oper, typename Body>
|
|
typename proto::result_of::make_expr<
|
|
tag::for_
|
|
, lldomain
|
|
, Init const &
|
|
, Cond const &
|
|
, Oper const &
|
|
, Body const &
|
|
>::type const
|
|
for_loop(Init const &init, Cond const &cond, Oper const &oper, Body const &body)
|
|
{
|
|
return proto::make_expr<tag::for_>(
|
|
boost::ref(init)
|
|
, boost::ref(cond)
|
|
, boost::ref(oper)
|
|
, boost::ref(body)
|
|
);
|
|
}
|
|
|
|
template<typename Cond, typename Body>
|
|
typename proto::result_of::make_expr<
|
|
tag::while_
|
|
, lldomain
|
|
, Cond const &
|
|
, Body const &
|
|
>::type const
|
|
while_loop(Cond const &cond, Body const &body)
|
|
{
|
|
return proto::make_expr<tag::while_, lldomain>(
|
|
boost::ref(cond)
|
|
, boost::ref(body)
|
|
);
|
|
}
|
|
|
|
template<typename Cond>
|
|
typename proto::result_of::make_expr<
|
|
tag::while_
|
|
, lldomain
|
|
, Cond const &
|
|
, noop_type const &
|
|
>::type const
|
|
while_loop(Cond const &cond)
|
|
{
|
|
return proto::make_expr<tag::while_, lldomain>(
|
|
boost::ref(cond)
|
|
, boost::ref(noop)
|
|
);
|
|
}
|
|
|
|
template<typename Cond, typename Body>
|
|
typename proto::result_of::make_expr<
|
|
tag::do_while_
|
|
, lldomain
|
|
, Body const &
|
|
, Cond const &
|
|
>::type const
|
|
do_while_loop(Cond const &cond, Body const &body)
|
|
{
|
|
return proto::make_expr<tag::do_while_, lldomain>(
|
|
boost::ref(body)
|
|
, boost::ref(cond)
|
|
);
|
|
}
|
|
|
|
template<typename Cond>
|
|
typename proto::result_of::make_expr<
|
|
tag::do_while_
|
|
, lldomain
|
|
, noop_type const &
|
|
, Cond const &
|
|
>::type const
|
|
do_while_loop(Cond const &cond)
|
|
{
|
|
return proto::make_expr<tag::do_while_, lldomain>(
|
|
boost::ref(noop)
|
|
, boost::ref(cond)
|
|
);
|
|
}
|
|
|
|
template<typename Cond, typename Body1>
|
|
typename proto::result_of::make_expr<
|
|
tag::if_
|
|
, lldomain
|
|
, Cond const &
|
|
, Body1 const &
|
|
>::type const
|
|
if_then(Cond const &cond, Body1 const &body1)
|
|
{
|
|
return proto::make_expr<tag::if_, lldomain>(
|
|
boost::ref(cond)
|
|
, boost::ref(body1)
|
|
);
|
|
}
|
|
|
|
template<typename Cond, typename Body1, typename Body2>
|
|
typename proto::result_of::make_expr<
|
|
tag::if_else_
|
|
, lldomain
|
|
, Cond const &
|
|
, Body1 const &
|
|
, Body2 const &
|
|
>::type const
|
|
if_then_else(Cond const &cond, Body1 const &body1, Body2 const &body2)
|
|
{
|
|
return proto::make_expr<tag::if_else_, lldomain>(
|
|
boost::ref(cond)
|
|
, boost::ref(body1)
|
|
, boost::ref(body2)
|
|
);
|
|
}
|
|
|
|
template<typename Cond, typename Body1, typename Body2>
|
|
typename proto::result_of::make_expr<
|
|
proto::tag::if_else_
|
|
, lldomain
|
|
, Cond const &
|
|
, Body1 const &
|
|
, Body2 const &
|
|
>::type const
|
|
if_then_else_return(Cond const &cond, Body1 const &body1, Body2 const &body2)
|
|
{
|
|
return proto::make_expr<proto::tag::if_else_, lldomain>(
|
|
boost::ref(cond)
|
|
, boost::ref(body1)
|
|
, boost::ref(body2)
|
|
);
|
|
}
|
|
|
|
template<typename T>
|
|
T const &make_const(T const &t)
|
|
{
|
|
return t;
|
|
}
|
|
|
|
#define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
|
|
template<typename_A(N)> \
|
|
typename proto::result_of::make_expr< \
|
|
proto::tag::function \
|
|
, lldomain \
|
|
, A_const_ref(N) \
|
|
>::type const \
|
|
bind(A_const_ref_a(N)) \
|
|
{ \
|
|
return proto::make_expr<proto::tag::function, lldomain>(ref_a(N)); \
|
|
} \
|
|
\
|
|
template<typename Ret, typename_A(N)> \
|
|
typename proto::result_of::make_expr< \
|
|
proto::tag::function \
|
|
, lldomain \
|
|
, A_const_ref(N) \
|
|
>::type const \
|
|
bind(A_const_ref_a(N)) \
|
|
{ \
|
|
return proto::make_expr<proto::tag::function, lldomain>(ref_a(N)); \
|
|
} \
|
|
/**/
|
|
BOOST_PROTO_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1)
|
|
#undef M1
|
|
|
|
template<typename Ret, typename Expr>
|
|
Expr const &ret(Expr const &expr)
|
|
{
|
|
return expr;
|
|
}
|
|
|
|
template<typename Expr>
|
|
Expr const &const_parameters(Expr const &expr)
|
|
{
|
|
return expr;
|
|
}
|
|
|
|
template<typename Expr>
|
|
Expr const &break_const(Expr const &expr)
|
|
{
|
|
return expr;
|
|
}
|
|
|
|
template<typename Lambda>
|
|
proto::unexpr<Lambda> const
|
|
unlambda(Lambda const &lambda)
|
|
{
|
|
return proto::unexpr<Lambda>(lambda);
|
|
}
|
|
|
|
template<typename Lambda>
|
|
typename proto::result_of::make_expr<
|
|
tag::protect
|
|
, lldomain
|
|
, Lambda const &
|
|
>::type const
|
|
protect(Lambda const &lambda)
|
|
{
|
|
return proto::make_expr<tag::protect, lldomain>(boost::ref(lambda));
|
|
}
|
|
|
|
template<typename T>
|
|
T const std_functor(T const &t)
|
|
{
|
|
return t;
|
|
}
|
|
|
|
template<typename T>
|
|
struct ll_static_cast_fun
|
|
{
|
|
typedef T result_type;
|
|
|
|
template<typename U>
|
|
T operator()(U &u) const
|
|
{
|
|
return static_cast<T>(u);
|
|
}
|
|
|
|
template<typename U>
|
|
T operator()(U const &u) const
|
|
{
|
|
return static_cast<T>(u);
|
|
}
|
|
};
|
|
|
|
template<typename T, typename U>
|
|
typename proto::result_of::make_expr<
|
|
proto::tag::function
|
|
, lldomain
|
|
, ll_static_cast_fun<T>
|
|
, U const &
|
|
>::type
|
|
ll_static_cast(U const &u)
|
|
{
|
|
ll_static_cast_fun<T> fun;
|
|
return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
|
|
}
|
|
|
|
template<typename T>
|
|
struct ll_const_cast_fun
|
|
{
|
|
typedef T result_type;
|
|
|
|
template<typename U>
|
|
T operator()(U &u) const
|
|
{
|
|
return const_cast<T>(u);
|
|
}
|
|
|
|
template<typename U>
|
|
T operator()(U const &u) const
|
|
{
|
|
return const_cast<T>(u);
|
|
}
|
|
};
|
|
|
|
template<typename T, typename U>
|
|
typename proto::result_of::make_expr<
|
|
proto::tag::function
|
|
, lldomain
|
|
, ll_const_cast_fun<T>
|
|
, U const &
|
|
>::type
|
|
ll_const_cast(U const &u)
|
|
{
|
|
ll_const_cast_fun<T> fun;
|
|
return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
|
|
}
|
|
|
|
template<typename T>
|
|
struct ll_dynamic_cast_fun
|
|
{
|
|
typedef T result_type;
|
|
|
|
template<typename U>
|
|
T operator()(U &u) const
|
|
{
|
|
return dynamic_cast<T>(u);
|
|
}
|
|
|
|
template<typename U>
|
|
T operator()(U const &u) const
|
|
{
|
|
return dynamic_cast<T>(u);
|
|
}
|
|
};
|
|
|
|
template<typename T, typename U>
|
|
typename proto::result_of::make_expr<
|
|
proto::tag::function
|
|
, lldomain
|
|
, ll_dynamic_cast_fun<T>
|
|
, U const &
|
|
>::type
|
|
ll_dynamic_cast(U const &u)
|
|
{
|
|
ll_dynamic_cast_fun<T> fun;
|
|
return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
|
|
}
|
|
|
|
template<typename T>
|
|
struct ll_reinterpret_cast_fun
|
|
{
|
|
typedef T result_type;
|
|
|
|
template<typename U>
|
|
T operator()(U &u) const
|
|
{
|
|
return reinterpret_cast<T>(u);
|
|
}
|
|
|
|
template<typename U>
|
|
T operator()(U const &u) const
|
|
{
|
|
return reinterpret_cast<T>(u);
|
|
}
|
|
};
|
|
|
|
template<typename T, typename U>
|
|
typename proto::result_of::make_expr<
|
|
proto::tag::function
|
|
, lldomain
|
|
, ll_reinterpret_cast_fun<T>
|
|
, U const &
|
|
>::type
|
|
ll_reinterpret_cast(U const &u)
|
|
{
|
|
ll_reinterpret_cast_fun<T> fun;
|
|
return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
|
|
}
|
|
|
|
struct ll_sizeof_fun
|
|
{
|
|
typedef std::size_t result_type;
|
|
|
|
template<typename U>
|
|
std::size_t operator()(U const &) const
|
|
{
|
|
return sizeof(U);
|
|
}
|
|
};
|
|
|
|
template<typename U>
|
|
typename proto::result_of::make_expr<
|
|
proto::tag::function
|
|
, lldomain
|
|
, ll_sizeof_fun
|
|
, U const &
|
|
>::type
|
|
ll_sizeof(U const &u)
|
|
{
|
|
ll_sizeof_fun fun;
|
|
return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
|
|
}
|
|
|
|
struct ll_typeid_fun
|
|
{
|
|
typedef std::type_info const &result_type;
|
|
|
|
template<typename U>
|
|
std::type_info const &operator()(U const &) const
|
|
{
|
|
return typeid(U);
|
|
}
|
|
};
|
|
|
|
template<typename U>
|
|
typename proto::result_of::make_expr<
|
|
proto::tag::function
|
|
, lldomain
|
|
, ll_typeid_fun
|
|
, U const &
|
|
>::type
|
|
ll_typeid(U const &u)
|
|
{
|
|
ll_typeid_fun fun;
|
|
return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(u));
|
|
}
|
|
|
|
template<typename T>
|
|
struct constructor
|
|
{
|
|
typedef T result_type;
|
|
|
|
T operator()() const
|
|
{
|
|
return T();
|
|
}
|
|
|
|
#define M0(Z, N, DATA) \
|
|
template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \
|
|
T operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const \
|
|
{ \
|
|
return T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \
|
|
} \
|
|
/**/
|
|
BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~)
|
|
#undef M0
|
|
};
|
|
|
|
template<typename T>
|
|
struct new_ptr
|
|
{
|
|
typedef T *result_type;
|
|
|
|
T *operator()() const
|
|
{
|
|
return new T();
|
|
}
|
|
|
|
#define M0(Z, N, DATA) \
|
|
template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)> \
|
|
T *operator()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) const \
|
|
{ \
|
|
return new T(BOOST_PP_ENUM_PARAMS_Z(Z, N, a)); \
|
|
} \
|
|
/**/
|
|
BOOST_PP_REPEAT_FROM_TO(1, BOOST_PROTO_MAX_ARITY, M0, ~)
|
|
#undef M0
|
|
};
|
|
|
|
struct destructor
|
|
{
|
|
typedef void result_type;
|
|
|
|
template<typename T>
|
|
void operator()(T const &t) const
|
|
{
|
|
t.~T();
|
|
}
|
|
|
|
template<typename T>
|
|
void operator()(T *const &t) const
|
|
{
|
|
(*t).~T();
|
|
}
|
|
};
|
|
|
|
struct delete_ptr
|
|
{
|
|
typedef void result_type;
|
|
template<typename T>
|
|
void operator()(T *t) const
|
|
{
|
|
delete t;
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct new_array
|
|
{
|
|
typedef T *result_type;
|
|
T *operator()(std::size_t n) const
|
|
{
|
|
return new T[n];
|
|
}
|
|
};
|
|
|
|
struct delete_array
|
|
{
|
|
typedef void result_type;
|
|
template<typename T>
|
|
void operator()(T *t) const
|
|
{
|
|
delete[] t;
|
|
}
|
|
};
|
|
|
|
template<typename T>
|
|
struct type2type {};
|
|
|
|
struct try_catch_nil {};
|
|
|
|
template<typename Head, typename Tail>
|
|
struct try_catch_cons : Tail
|
|
{
|
|
typedef typename Head::proto_tag::exception_type exception_type;
|
|
|
|
try_catch_cons(Head const &head, Tail const &tail)
|
|
: Tail(tail)
|
|
, head(head)
|
|
{}
|
|
|
|
template<typename State, typename Data>
|
|
typename result_of<Tail const(State const &, Data &)>::type
|
|
operator()(State const &state, Data &data) const
|
|
{
|
|
return this->invoke(state, data, type2type<exception_type>());
|
|
}
|
|
|
|
private:
|
|
// catch(Exception const &)
|
|
template<typename State, typename Data, typename Exception>
|
|
typename result_of<Tail const(State const &, Data &)>::type
|
|
invoke(State const &state, Data &data, type2type<Exception>) const
|
|
{
|
|
typedef typename result_of<Tail const(State const &, Data &)>::type result_type;
|
|
try
|
|
{
|
|
return static_cast<result_type>(this->Tail::operator()(state, data));
|
|
}
|
|
catch(Exception const &e)
|
|
{
|
|
return static_cast<result_type>(Eval()(this->head, e, data));
|
|
}
|
|
}
|
|
|
|
// catch(...)
|
|
template<typename State, typename Data>
|
|
typename result_of<Tail const(State const &, Data &)>::type
|
|
invoke(State const &state, Data &data, type2type<tag::catch_all_>) const
|
|
{
|
|
typedef typename result_of<Tail const(State const &, Data &)>::type result_type;
|
|
try
|
|
{
|
|
return static_cast<result_type>(this->Tail::operator()(state, data));
|
|
}
|
|
catch(...)
|
|
{
|
|
return static_cast<result_type>(Eval()(this->head, tag::catch_all_(), data));
|
|
}
|
|
}
|
|
|
|
Head const &head;
|
|
};
|
|
|
|
template<typename Head>
|
|
struct try_catch_cons<Head, try_catch_nil> : proto::callable
|
|
{
|
|
try_catch_cons(Head const &head, try_catch_nil const &)
|
|
: head(head)
|
|
{}
|
|
|
|
template<typename Sig>
|
|
struct result;
|
|
|
|
template<typename This, typename State, typename Data>
|
|
struct result<This(State, Data)>
|
|
: result_of<Eval(Head const &, State, Data)>
|
|
{};
|
|
|
|
template<typename State, typename Data>
|
|
typename result_of<Eval(Head const &, State, Data)>::type
|
|
operator()(State const &state, Data &data) const
|
|
{
|
|
return Eval()(this->head, state, data);
|
|
}
|
|
|
|
private:
|
|
Head const &head;
|
|
};
|
|
|
|
struct try_catch_fun : proto::callable
|
|
{
|
|
template<typename Sig>
|
|
struct result;
|
|
|
|
template<typename This, typename Fun, typename State, typename Data>
|
|
struct result<This(Fun, State, Data)>
|
|
: result_of<Fun(State, Data)>
|
|
{};
|
|
|
|
template<typename Fun, typename State, typename Data>
|
|
typename result_of<Fun(State const &, Data &)>::type
|
|
operator()(Fun const &fun, State const &state, Data &data) const
|
|
{
|
|
return fun(state, data);
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct Cases::case_<tag::try_>
|
|
: proto::otherwise<
|
|
try_catch_fun(
|
|
proto::fold<
|
|
proto::_
|
|
, try_catch_nil()
|
|
, try_catch_cons<proto::_, proto::_state>(proto::_, proto::_state)
|
|
>
|
|
, proto::_state
|
|
, proto::_data
|
|
)
|
|
>
|
|
{};
|
|
|
|
template<typename E, typename Expr>
|
|
typename proto::result_of::make_expr<tag::catch_<E>, lldomain, Expr const &>::type const
|
|
catch_exception(Expr const &expr)
|
|
{
|
|
return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(expr));
|
|
}
|
|
|
|
template<typename E>
|
|
typename proto::result_of::make_expr<tag::catch_<E>, lldomain, noop_type const &>::type const
|
|
catch_exception()
|
|
{
|
|
return proto::make_expr<tag::catch_<E>, lldomain>(boost::ref(noop));
|
|
}
|
|
|
|
template<typename Expr>
|
|
typename proto::result_of::make_expr<
|
|
tag::catch_all_
|
|
, lldomain
|
|
, Expr const &
|
|
>::type const
|
|
catch_all(Expr const &expr)
|
|
{
|
|
return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(expr));
|
|
}
|
|
|
|
inline
|
|
proto::result_of::make_expr<tag::catch_all_, lldomain, noop_type const &>::type const
|
|
catch_all()
|
|
{
|
|
return proto::make_expr<tag::catch_all_, lldomain>(boost::ref(noop));
|
|
}
|
|
|
|
#define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
|
|
template<typename_A(N)> \
|
|
typename proto::result_of::make_expr< \
|
|
tag::try_ \
|
|
, lldomain \
|
|
, A_const_ref(N) \
|
|
>::type const \
|
|
try_catch(A_const_ref_a(N)) \
|
|
{ \
|
|
return proto::make_expr<tag::try_, lldomain>(ref_a(N)); \
|
|
} \
|
|
/**/
|
|
BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1)
|
|
#undef M1
|
|
|
|
template<typename Expr>
|
|
typename proto::result_of::make_expr<
|
|
proto::tag::function
|
|
, lldomain
|
|
, throw_fun
|
|
, Expr const &
|
|
>::type const
|
|
throw_exception(Expr const &expr)
|
|
{
|
|
throw_fun fun;
|
|
return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(expr));
|
|
}
|
|
|
|
inline
|
|
proto::result_of::make_expr<proto::tag::function, lldomain, rethrow_fun>::type const
|
|
rethrow()
|
|
{
|
|
return proto::make_expr<proto::tag::function, lldomain>(rethrow_fun());
|
|
}
|
|
|
|
struct make_void_fun
|
|
{
|
|
typedef void result_type;
|
|
template<typename T>
|
|
void operator()(T const &) const
|
|
{}
|
|
};
|
|
|
|
template<typename Expr>
|
|
typename proto::result_of::make_expr<
|
|
proto::tag::function
|
|
, lldomain
|
|
, make_void_fun
|
|
, Expr const &
|
|
>::type const
|
|
make_void(Expr const &expr)
|
|
{
|
|
make_void_fun fun;
|
|
return proto::make_expr<proto::tag::function, lldomain>(fun, boost::ref(expr));
|
|
}
|
|
|
|
#define M1(N, typename_A, A_const_ref, A_const_ref_a, ref_a) \
|
|
template<typename_A(N)> \
|
|
typename proto::result_of::make_expr< \
|
|
tag::switch_ \
|
|
, lldomain \
|
|
, A_const_ref(N) \
|
|
>::type const \
|
|
switch_statement(A_const_ref_a(N)) \
|
|
{ \
|
|
return proto::make_expr<tag::switch_, lldomain>(ref_a(N)); \
|
|
} \
|
|
/**/
|
|
BOOST_PROTO_REPEAT_FROM_TO(2, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), M1)
|
|
#undef M1
|
|
|
|
template<int I, typename Expr>
|
|
typename proto::result_of::make_expr<tag::case_<I>, lldomain, Expr const &>::type const
|
|
case_statement(Expr const &expr)
|
|
{
|
|
return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(expr));
|
|
}
|
|
|
|
template<int I>
|
|
typename proto::result_of::make_expr<tag::case_<I>, lldomain, noop_type const &>::type const
|
|
case_statement()
|
|
{
|
|
return proto::make_expr<tag::case_<I>, lldomain>(boost::ref(noop));
|
|
}
|
|
|
|
template<typename Expr>
|
|
typename proto::result_of::make_expr<tag::default_, lldomain, Expr const &>::type const
|
|
default_statement(Expr const &expr)
|
|
{
|
|
return proto::make_expr<tag::default_, lldomain>(boost::ref(expr));
|
|
}
|
|
|
|
inline
|
|
proto::result_of::make_expr<tag::default_, lldomain, noop_type const &>::type const
|
|
default_statement()
|
|
{
|
|
return proto::make_expr<tag::default_, lldomain>(boost::ref(noop));
|
|
}
|
|
|
|
namespace ll
|
|
{
|
|
struct for_each
|
|
{
|
|
template<typename Sig>
|
|
struct result;
|
|
|
|
template<typename This, typename Begin, typename End, typename Fun>
|
|
struct result<This(Begin, End, Fun)>
|
|
: remove_const<typename remove_reference<Fun>::type>
|
|
{};
|
|
|
|
template<typename InIter, typename Fun>
|
|
Fun operator()(InIter begin, InIter end, Fun fun) const
|
|
{
|
|
return std::for_each(begin, end, fun);
|
|
}
|
|
};
|
|
}
|
|
|
|
}}
|
|
|
|
namespace boost
|
|
{
|
|
template<typename Expr>
|
|
struct result_of<lambda::llexpr<Expr>()>
|
|
: lambda::llexpr<Expr>::template result<lambda::llexpr<Expr>()>
|
|
{};
|
|
|
|
template<typename Expr>
|
|
struct result_of<lambda::llexpr<Expr> const()>
|
|
: lambda::llexpr<Expr>::template result<lambda::llexpr<Expr> const()>
|
|
{};
|
|
}
|
|
|
|
#ifdef _MSC_VER
|
|
# pragma warning(pop)
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#else
|
|
|
|
BOOST_PP_SEQ_FOR_EACH_PRODUCT(
|
|
M2,
|
|
BOOST_PP_REPEAT(BOOST_PP_ITERATION(), M1, ~)
|
|
)
|
|
|
|
#endif
|