mirror of
https://github.com/boostorg/lambda.git
synced 2026-01-27 19:02:15 +00:00
added support for protect, unlambda, currying and break_const
[SVN r12139]
This commit is contained in:
@@ -424,6 +424,7 @@ struct return_type<
|
||||
template<class Args>
|
||||
class
|
||||
lambda_functor_base<action<4, return_void_action<forloop_action> >, Args> {
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
@@ -442,6 +443,7 @@ public:
|
||||
template<class Args>
|
||||
class
|
||||
lambda_functor_base<action<3, return_void_action<forloop_action> >, Args> {
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
@@ -459,6 +461,7 @@ public:
|
||||
template<class Args>
|
||||
class
|
||||
lambda_functor_base<action<2, return_void_action<whileloop_action> >, Args> {
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
@@ -475,6 +478,7 @@ public:
|
||||
template<class Args>
|
||||
class
|
||||
lambda_functor_base<action<1, return_void_action<whileloop_action> >, Args> {
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
@@ -490,6 +494,7 @@ public:
|
||||
template<class Args>
|
||||
class
|
||||
lambda_functor_base<action<2, return_void_action<dowhileloop_action> >, Args> {
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
@@ -506,6 +511,7 @@ public:
|
||||
template<class Args>
|
||||
class
|
||||
lambda_functor_base<action<1, return_void_action<dowhileloop_action> >, Args> {
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
@@ -521,6 +527,7 @@ public:
|
||||
template<class Args>
|
||||
class
|
||||
lambda_functor_base<action<2, return_void_action<ifthen_action> >, Args> {
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
@@ -535,6 +542,7 @@ public:
|
||||
template<class Args>
|
||||
class
|
||||
lambda_functor_base<action<3, return_void_action<ifthenelse_action> >, Args> {
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
@@ -552,6 +560,7 @@ public:
|
||||
template<class Args>
|
||||
class
|
||||
lambda_functor_base<action<3, other_action<ifthenelsereturn_action> >, Args> {
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
|
||||
@@ -57,6 +57,7 @@ struct nth_return_type {
|
||||
template<class RET, class Args>
|
||||
class lambda_functor_base<action<1, explicit_return_type_action<RET> >, Args>
|
||||
{
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
|
||||
@@ -77,6 +78,7 @@ public:
|
||||
template<class Args>
|
||||
class lambda_functor_base<action<1, protect_action >, Args>
|
||||
{
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
|
||||
@@ -90,6 +92,65 @@ public:
|
||||
};
|
||||
|
||||
|
||||
// The work of curry action is not defined in action class apply,
|
||||
// but rather directly in lambda_functor_base::call
|
||||
// The argument substitution would be messed up otherwise.
|
||||
|
||||
// the curry_action 2-ary lambda_functor, one curried arg -------------------
|
||||
template<class Args>
|
||||
class lambda_functor_base<action<3, curry_action<1> >, Args>
|
||||
{
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
|
||||
template<class RET, class A, class B, class C>
|
||||
RET call(A& a, B& b, C& c) const
|
||||
{
|
||||
return boost::tuples::get<0>(args).template ret_call<RET>(
|
||||
boost::tuples::get<1>(args), a);
|
||||
}
|
||||
};
|
||||
|
||||
// the curry_action case, 3-ary lambda functor, one curried arg --------------
|
||||
template<class Args>
|
||||
class lambda_functor_base<action<4, curry_action<1> >, Args>
|
||||
{
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
|
||||
template<class RET, class A, class B, class C>
|
||||
RET call(A& a, B& b, C& c) const
|
||||
{
|
||||
return boost::tuples::get<0>(args).template ret_call<RET>(
|
||||
boost::tuples::get<1>(args), a, b);
|
||||
}
|
||||
};
|
||||
|
||||
// the curry_action case, 3-ary lambda functor, two curried args -------------
|
||||
template<class Args>
|
||||
class lambda_functor_base<action<4, curry_action<2> >, Args>
|
||||
{
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
|
||||
template<class RET, class A, class B, class C>
|
||||
RET call(A& a, B& b, C& c) const
|
||||
{
|
||||
return boost::tuples::get<0>(args).template ret_call<RET>(
|
||||
boost::tuples::get<1>(args), boost::tuples::get<2>(args), a);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#if defined BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART
|
||||
#error "Multiple defines of BOOST_LAMBDA_LAMBDA_FUNCTOR_BASE_FIRST_PART"
|
||||
#endif
|
||||
@@ -98,6 +159,7 @@ public:
|
||||
template<class Act, class Args>\
|
||||
class lambda_functor_base<action<ARITY, Act>, Args> \
|
||||
{\
|
||||
public:\
|
||||
Args args;\
|
||||
public:\
|
||||
\
|
||||
|
||||
@@ -88,6 +88,7 @@ public:
|
||||
// default constructor (do nothing)
|
||||
// bug in gcc 2.95.2 for const template objects.
|
||||
|
||||
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
|
||||
|
||||
@@ -186,11 +187,35 @@ public:
|
||||
>::type>(a, b, const_null_type());
|
||||
}
|
||||
|
||||
// currying call: creates another lambda functor
|
||||
template<class A>
|
||||
lambda_functor<
|
||||
lambda_functor_args<
|
||||
action<3, curry_action<1> >,
|
||||
detail::bind_tuple_mapper<lambda_functor, const A>::type,
|
||||
FIRST
|
||||
>
|
||||
>
|
||||
operator()(A& a) const
|
||||
{
|
||||
return
|
||||
lambda_functor<
|
||||
lambda_functor_args<
|
||||
action<3, curry_action<1> >,
|
||||
detail::bind_tuple_mapper<lambda_functor, const A>::type,
|
||||
FIRST
|
||||
>
|
||||
> ( typename
|
||||
detail::bind_tuple_mapper<lambda_functor, const A>::type(*this, a)
|
||||
);
|
||||
}
|
||||
|
||||
template<class RET, class A, class B>
|
||||
RET ret_call(A& a, B& b) const {
|
||||
return inherited::template call<RET>(a, b, const_null_type());
|
||||
}
|
||||
|
||||
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
|
||||
|
||||
@@ -219,6 +244,55 @@ public:
|
||||
return inherited::template call<RET>(a, b, c);
|
||||
}
|
||||
|
||||
// currying call, one argument still missing
|
||||
template<class A, class B>
|
||||
lambda_functor<
|
||||
lambda_functor_args<
|
||||
action<4, curry_action<2> >,
|
||||
detail::bind_tuple_mapper<lambda_functor, const A, const B>::type,
|
||||
FIRST
|
||||
>
|
||||
>
|
||||
operator()(A& a, B& b) const
|
||||
{
|
||||
return
|
||||
lambda_functor<
|
||||
lambda_functor_args<
|
||||
action<4, curry_action<2> >,
|
||||
detail::bind_tuple_mapper<lambda_functor, const A, const B>::type,
|
||||
FIRST
|
||||
>
|
||||
>
|
||||
( typename
|
||||
detail::bind_tuple_mapper<lambda_functor, const A, const B>::type
|
||||
(*this, a, b)
|
||||
);
|
||||
}
|
||||
|
||||
// currying call, two arguments still missing
|
||||
template<class A>
|
||||
lambda_functor<
|
||||
lambda_functor_args<
|
||||
action<4, curry_action<1> >,
|
||||
detail::bind_tuple_mapper<lambda_functor, const A>::type,
|
||||
SECOND
|
||||
>
|
||||
>
|
||||
operator()(A& a) const
|
||||
{
|
||||
return
|
||||
lambda_functor<
|
||||
lambda_functor_args<
|
||||
action<4, curry_action<1> >,
|
||||
detail::bind_tuple_mapper<lambda_functor, const A>::type,
|
||||
SECOND
|
||||
>
|
||||
> ( typename
|
||||
detail::bind_tuple_mapper<lambda_functor, const A>::type(*this, a)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT
|
||||
BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT
|
||||
|
||||
@@ -251,6 +325,82 @@ public:
|
||||
|
||||
};
|
||||
|
||||
// This subclass adds lambda functors the ability to be copied,
|
||||
// if the functors are 'copy compatible'
|
||||
// This ability is needed, if lambda functor evaluation results in
|
||||
// a lambda functor (e.g. with protect).
|
||||
template <class Act, class Args, int Code>
|
||||
struct lambda_functor_sub<lambda_functor_args<Act, Args, Code> >
|
||||
: public lambda_functor<lambda_functor_args<Act, Args, Code> > {
|
||||
|
||||
// as long as action and arity are the same, lambda functors are convertible
|
||||
// if the argument tuples are.
|
||||
template <class Args2> lambda_functor_sub
|
||||
(const lambda_functor<lambda_functor_args<Act, Args2, Code> >& f)
|
||||
: lambda_functor<lambda_functor_args<Act, Args, Code> >(f.args) {}
|
||||
};
|
||||
|
||||
// any lambda functor can turned into const_incorrect_lambda_functor
|
||||
// The opreator() takes arguments as consts and then casts constness
|
||||
// away. So this breaks const correctness!!! but is a necessary workaround
|
||||
// in some cases due to language limitations.
|
||||
// Note, that this is not a lambda_functor anymore, so it can not be used
|
||||
// as a sub lambda expression.
|
||||
template <class Arg>
|
||||
struct const_incorrect_lambda_functor
|
||||
: private lambda_functor<Arg> {
|
||||
public:
|
||||
BOOST_STATIC_ASSERT(dig_arity<Arg>::value <= THIRD);
|
||||
// only allowed for normal lambda functions, not EXCEPTION ones
|
||||
|
||||
typedef lambda_functor<Arg> inherited;
|
||||
|
||||
explicit const_incorrect_lambda_functor(const lambda_functor<Arg>& lf)
|
||||
: inherited(lf.args) {}
|
||||
|
||||
|
||||
// This is provided just for completeness; no arguments, no constness
|
||||
// problems.
|
||||
typename return_type<inherited,
|
||||
open_args<null_type, null_type, null_type> >::type
|
||||
operator()() const
|
||||
{
|
||||
return inherited::template ret_call<
|
||||
typename return_type<
|
||||
inherited,
|
||||
open_args<null_type, null_type, null_type>
|
||||
>::type>();
|
||||
}
|
||||
|
||||
template<class A>
|
||||
typename return_type<inherited, open_args<A&, null_type, null_type> >::type
|
||||
operator()(const A& a) const
|
||||
{
|
||||
return inherited::template ret_call<
|
||||
typename return_type<inherited, open_args<A&, null_type, null_type>
|
||||
>::type>(const_cast<A&>(a));
|
||||
}
|
||||
template<class A, class B>
|
||||
typename return_type<inherited, open_args<A&, B&, null_type> >::type
|
||||
operator()(const A& a, const B& b) const
|
||||
{
|
||||
return inherited::template ret_call<
|
||||
typename return_type<inherited, open_args<A&, B&, null_type>
|
||||
>::type>(const_cast<A&>(a), const_cast<B&>(b));
|
||||
}
|
||||
template<class A, class B, class C>
|
||||
typename return_type<inherited, open_args<A&, B&, C&> >::type
|
||||
operator()(const A& a, const B& b, const C& c) const
|
||||
{
|
||||
return inherited::template ret_call<
|
||||
typename return_type<inherited, open_args<A&, B&, C&>
|
||||
>::type>(const_cast<A&>(a), const_cast<B&>(b), const_cast<C&>(c));
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
// -- free variables types --------------------------------------------------
|
||||
|
||||
template <int I> class placeholder {};
|
||||
|
||||
@@ -43,6 +43,9 @@ template <int I, class Act> class action;
|
||||
template <class BinderArgs>
|
||||
struct lambda_functor;
|
||||
|
||||
template <class BinderArgs>
|
||||
struct lambda_functor_sub;
|
||||
|
||||
template <class Action,
|
||||
class Args,
|
||||
int ArityCode>
|
||||
|
||||
@@ -147,6 +147,12 @@ template <class T> struct is_lambda_functor_ {
|
||||
template <class Arg> struct is_lambda_functor_<lambda_functor<Arg> > {
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
// lambda_functor_sub goes for lambda functor as well
|
||||
template <class Arg> struct is_lambda_functor_<lambda_functor_sub<Arg> > {
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
|
||||
} // end detail
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace lambda {
|
||||
// Specialization for comma.
|
||||
template<class Args>
|
||||
class lambda_functor_base<action<2, other_action<comma_action> >, Args> {
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
@@ -43,6 +44,7 @@ public:
|
||||
// Specialization for logical and (to preserve shortcircuiting)
|
||||
template<class Args>
|
||||
class lambda_functor_base<action<2, logical_action<and_action> >, Args> {
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
@@ -57,6 +59,7 @@ public:
|
||||
// Specialization for logical or (to preserve shortcircuiting)
|
||||
template<class Args>
|
||||
class lambda_functor_base<action<2, logical_action< or_action> >, Args> {
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
|
||||
@@ -45,6 +45,10 @@ ret(const lambda_functor<Arg>& a1)
|
||||
|
||||
// protect ------------------
|
||||
|
||||
// protecting others than lambda functors has no effect
|
||||
template <class T>
|
||||
inline const T& protect(const T& t) { return t; }
|
||||
|
||||
template<class Arg>
|
||||
inline const
|
||||
lambda_functor<
|
||||
@@ -66,7 +70,6 @@ protect(const lambda_functor<Arg>& a1)
|
||||
(tuple<lambda_functor<Arg> >(a1));
|
||||
}
|
||||
|
||||
|
||||
// -- identity -------------------------
|
||||
// identity templates
|
||||
template<class Arg>
|
||||
@@ -143,8 +146,78 @@ public:
|
||||
> type;
|
||||
};
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// Hides the lambda functorness of a lambda functor.
|
||||
// After this, the functor is immune to argument substitution, etc.
|
||||
// This can be used, e.g. to make it safe to pass lambda functors as
|
||||
// arguments to functions, which might use them as target functions
|
||||
|
||||
// note, unlambda and protect are different things. Protect hides the lambda
|
||||
// functor for one application, unlambda for good.
|
||||
|
||||
template <class Arg>
|
||||
class non_lambda_functor {
|
||||
lambda_functor<Arg> lf; // a lambda functor
|
||||
public:
|
||||
|
||||
// This functor defines the result_type typedef.
|
||||
// The result type must be deducible without knowing the arguments
|
||||
|
||||
// TODO: check that passing unspecified as open args fails
|
||||
typedef typename
|
||||
return_type<Arg,
|
||||
open_args<detail::unspecified,
|
||||
detail::unspecified,
|
||||
detail::unspecified> >::type
|
||||
result_type;
|
||||
|
||||
non_lambda_functor(const lambda_functor<Arg>& a) : lf(a) {}
|
||||
|
||||
result_type operator()() const {
|
||||
return lf.template ret_call<result_type>();
|
||||
}
|
||||
|
||||
template<class A>
|
||||
result_type operator()(A& a) const {
|
||||
return lf.template ret_call<result_type>(a);
|
||||
}
|
||||
|
||||
template<class A, class B>
|
||||
result_type operator()(A& a, B& b) const {
|
||||
return lf.template ret_call<result_type>(a, b);
|
||||
}
|
||||
|
||||
template<class A, class B, class C>
|
||||
result_type operator()(A& a, B& b, C& c) const {
|
||||
return lf.template ret_call<result_type>(a, b, c);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Arg>
|
||||
inline const Arg& unlambda(const Arg& a) { return a; }
|
||||
|
||||
template <class Arg>
|
||||
inline const non_lambda_functor<Arg> unlambda(const lambda_functor<Arg>& a)
|
||||
{
|
||||
return non_lambda_functor<Arg>(a);
|
||||
};
|
||||
|
||||
// Due to a language restriction, lambda functors cannot be made to
|
||||
// accept non-const rvalue arguments. Usually iterators do not return
|
||||
// temporaries, but sometimes they do. That's why a workaround is provided.
|
||||
// Note, that this potentially breaks const correctness, so be careful!
|
||||
|
||||
template <class Arg>
|
||||
inline const const_incorrect_lambda_functor<Arg>
|
||||
break_const(const lambda_functor<Arg>& lf)
|
||||
{
|
||||
return const_incorrect_lambda_functor<Arg>(lf);
|
||||
}
|
||||
|
||||
} // namespace lambda
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -149,6 +149,7 @@ lambda_functor_base<
|
||||
Args
|
||||
>
|
||||
{
|
||||
public:
|
||||
Args args;
|
||||
public:
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {}
|
||||
@@ -334,7 +335,8 @@ lambda_functor_base< \
|
||||
>, \
|
||||
Args \
|
||||
> \
|
||||
{ \
|
||||
{ \
|
||||
public: \
|
||||
Args args; \
|
||||
public: \
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {} \
|
||||
@@ -370,6 +372,7 @@ lambda_functor_base< \
|
||||
Args \
|
||||
> \
|
||||
{ \
|
||||
public: \
|
||||
Args args; \
|
||||
public: \
|
||||
explicit lambda_functor_base(const Args& a) : args(a) {} \
|
||||
|
||||
Reference in New Issue
Block a user