diff --git a/include/boost/lambda/detail/control_structures_impl.hpp b/include/boost/lambda/detail/control_structures_impl.hpp index b575ffa..9b9a601 100644 --- a/include/boost/lambda/detail/control_structures_impl.hpp +++ b/include/boost/lambda/detail/control_structures_impl.hpp @@ -424,6 +424,7 @@ struct return_type< template class lambda_functor_base >, Args> { +public: Args args; public: explicit lambda_functor_base(const Args& a) : args(a) {} @@ -442,6 +443,7 @@ public: template class lambda_functor_base >, Args> { +public: Args args; public: explicit lambda_functor_base(const Args& a) : args(a) {} @@ -459,6 +461,7 @@ public: template class lambda_functor_base >, Args> { +public: Args args; public: explicit lambda_functor_base(const Args& a) : args(a) {} @@ -475,6 +478,7 @@ public: template class lambda_functor_base >, Args> { +public: Args args; public: explicit lambda_functor_base(const Args& a) : args(a) {} @@ -490,6 +494,7 @@ public: template class lambda_functor_base >, Args> { +public: Args args; public: explicit lambda_functor_base(const Args& a) : args(a) {} @@ -506,6 +511,7 @@ public: template class lambda_functor_base >, Args> { +public: Args args; public: explicit lambda_functor_base(const Args& a) : args(a) {} @@ -521,6 +527,7 @@ public: template class lambda_functor_base >, Args> { +public: Args args; public: explicit lambda_functor_base(const Args& a) : args(a) {} @@ -535,6 +542,7 @@ public: template class lambda_functor_base >, Args> { +public: Args args; public: explicit lambda_functor_base(const Args& a) : args(a) {} @@ -552,6 +560,7 @@ public: template class lambda_functor_base >, Args> { +public: Args args; public: explicit lambda_functor_base(const Args& a) : args(a) {} diff --git a/include/boost/lambda/detail/lambda_functor_base.hpp b/include/boost/lambda/detail/lambda_functor_base.hpp index 5e7df62..62a8de1 100644 --- a/include/boost/lambda/detail/lambda_functor_base.hpp +++ b/include/boost/lambda/detail/lambda_functor_base.hpp @@ -57,6 +57,7 @@ struct nth_return_type { template class lambda_functor_base >, Args> { +public: Args args; public: @@ -77,6 +78,7 @@ public: template class lambda_functor_base, 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 lambda_functor_base >, Args> +{ +public: + Args args; +public: + + explicit lambda_functor_base(const Args& a) : args(a) {} + + template + RET call(A& a, B& b, C& c) const + { + return boost::tuples::get<0>(args).template ret_call( + boost::tuples::get<1>(args), a); + } +}; + +// the curry_action case, 3-ary lambda functor, one curried arg -------------- +template +class lambda_functor_base >, Args> +{ +public: + Args args; +public: + + explicit lambda_functor_base(const Args& a) : args(a) {} + + template + RET call(A& a, B& b, C& c) const + { + return boost::tuples::get<0>(args).template ret_call( + boost::tuples::get<1>(args), a, b); + } +}; + +// the curry_action case, 3-ary lambda functor, two curried args ------------- +template +class lambda_functor_base >, Args> +{ +public: + Args args; +public: + + explicit lambda_functor_base(const Args& a) : args(a) {} + + template + RET call(A& a, B& b, C& c) const + { + return boost::tuples::get<0>(args).template ret_call( + 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 lambda_functor_base, Args> \ {\ +public:\ Args args;\ public:\ \ diff --git a/include/boost/lambda/detail/lambda_functors.hpp b/include/boost/lambda/detail/lambda_functors.hpp index c94f183..82549c9 100644 --- a/include/boost/lambda/detail/lambda_functors.hpp +++ b/include/boost/lambda/detail/lambda_functors.hpp @@ -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 + lambda_functor< + lambda_functor_args< + action<3, curry_action<1> >, + detail::bind_tuple_mapper::type, + FIRST + > + > + operator()(A& a) const + { + return + lambda_functor< + lambda_functor_args< + action<3, curry_action<1> >, + detail::bind_tuple_mapper::type, + FIRST + > + > ( typename + detail::bind_tuple_mapper::type(*this, a) + ); + } + template RET ret_call(A& a, B& b) const { return inherited::template call(a, b, const_null_type()); } + BOOST_LAMBDA_LAMBDA_FUNCTOR_ASSIGNMENT BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT @@ -219,6 +244,55 @@ public: return inherited::template call(a, b, c); } + // currying call, one argument still missing + template + lambda_functor< + lambda_functor_args< + action<4, curry_action<2> >, + detail::bind_tuple_mapper::type, + FIRST + > + > + operator()(A& a, B& b) const + { + return + lambda_functor< + lambda_functor_args< + action<4, curry_action<2> >, + detail::bind_tuple_mapper::type, + FIRST + > + > + ( typename + detail::bind_tuple_mapper::type + (*this, a, b) + ); + } + + // currying call, two arguments still missing + template + lambda_functor< + lambda_functor_args< + action<4, curry_action<1> >, + detail::bind_tuple_mapper::type, + SECOND + > + > + operator()(A& a) const + { + return + lambda_functor< + lambda_functor_args< + action<4, curry_action<1> >, + detail::bind_tuple_mapper::type, + SECOND + > + > ( typename + detail::bind_tuple_mapper::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 +struct lambda_functor_sub > + : public lambda_functor > { + + // as long as action and arity are the same, lambda functors are convertible + // if the argument tuples are. + template lambda_functor_sub + (const lambda_functor >& f) + : lambda_functor >(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 +struct const_incorrect_lambda_functor + : private lambda_functor { +public: + BOOST_STATIC_ASSERT(dig_arity::value <= THIRD); + // only allowed for normal lambda functions, not EXCEPTION ones + + typedef lambda_functor inherited; + + explicit const_incorrect_lambda_functor(const lambda_functor& lf) + : inherited(lf.args) {} + + + // This is provided just for completeness; no arguments, no constness + // problems. + typename return_type >::type + operator()() const + { + return inherited::template ret_call< + typename return_type< + inherited, + open_args + >::type>(); + } + + template + typename return_type >::type + operator()(const A& a) const + { + return inherited::template ret_call< + typename return_type + >::type>(const_cast(a)); + } + template + typename return_type >::type + operator()(const A& a, const B& b) const + { + return inherited::template ret_call< + typename return_type + >::type>(const_cast(a), const_cast(b)); + } + template + typename return_type >::type + operator()(const A& a, const B& b, const C& c) const + { + return inherited::template ret_call< + typename return_type + >::type>(const_cast(a), const_cast(b), const_cast(c)); + } + + +}; + + // -- free variables types -------------------------------------------------- template class placeholder {}; diff --git a/include/boost/lambda/detail/lambda_fwd.hpp b/include/boost/lambda/detail/lambda_fwd.hpp index cd3b051..c7c9dff 100644 --- a/include/boost/lambda/detail/lambda_fwd.hpp +++ b/include/boost/lambda/detail/lambda_fwd.hpp @@ -43,6 +43,9 @@ template class action; template struct lambda_functor; +template +struct lambda_functor_sub; + template diff --git a/include/boost/lambda/detail/lambda_traits.hpp b/include/boost/lambda/detail/lambda_traits.hpp index 80d4bb7..25d5884 100644 --- a/include/boost/lambda/detail/lambda_traits.hpp +++ b/include/boost/lambda/detail/lambda_traits.hpp @@ -147,6 +147,12 @@ template struct is_lambda_functor_ { template struct is_lambda_functor_ > { BOOST_STATIC_CONSTANT(bool, value = true); }; + +// lambda_functor_sub goes for lambda functor as well +template struct is_lambda_functor_ > { + BOOST_STATIC_CONSTANT(bool, value = true); +}; + } // end detail diff --git a/include/boost/lambda/detail/operator_lambda_functor_base.hpp b/include/boost/lambda/detail/operator_lambda_functor_base.hpp index 1887ce2..2fcc32d 100644 --- a/include/boost/lambda/detail/operator_lambda_functor_base.hpp +++ b/include/boost/lambda/detail/operator_lambda_functor_base.hpp @@ -29,6 +29,7 @@ namespace lambda { // Specialization for comma. template class lambda_functor_base >, 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 lambda_functor_base >, 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 lambda_functor_base >, Args> { +public: Args args; public: explicit lambda_functor_base(const Args& a) : args(a) {} diff --git a/include/boost/lambda/detail/ret.hpp b/include/boost/lambda/detail/ret.hpp index 68e40e6..5059647 100644 --- a/include/boost/lambda/detail/ret.hpp +++ b/include/boost/lambda/detail/ret.hpp @@ -45,6 +45,10 @@ ret(const lambda_functor& a1) // protect ------------------ + // protecting others than lambda functors has no effect +template +inline const T& protect(const T& t) { return t; } + template inline const lambda_functor< @@ -66,7 +70,6 @@ protect(const lambda_functor& a1) (tuple >(a1)); } - // -- identity ------------------------- // identity templates template @@ -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 non_lambda_functor { + lambda_functor 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 >::type + result_type; + + non_lambda_functor(const lambda_functor& a) : lf(a) {} + + result_type operator()() const { + return lf.template ret_call(); + } + + template + result_type operator()(A& a) const { + return lf.template ret_call(a); + } + + template + result_type operator()(A& a, B& b) const { + return lf.template ret_call(a, b); + } + + template + result_type operator()(A& a, B& b, C& c) const { + return lf.template ret_call(a, b, c); + } +}; + +template +inline const Arg& unlambda(const Arg& a) { return a; } + +template +inline const non_lambda_functor unlambda(const lambda_functor& a) +{ + return non_lambda_functor(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 +inline const const_incorrect_lambda_functor +break_const(const lambda_functor& lf) +{ + return const_incorrect_lambda_functor(lf); +} } // namespace lambda } // namespace boost #endif + diff --git a/include/boost/lambda/detail/switch.hpp b/include/boost/lambda/detail/switch.hpp index e64384a..fe22b9e 100644 --- a/include/boost/lambda/detail/switch.hpp +++ b/include/boost/lambda/detail/switch.hpp @@ -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) {} \