From 2c8b1949eccb9da8cb979ba118d84dfd7c582c96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20J=C3=A4rvi?= Date: Fri, 21 Dec 2001 19:27:26 +0000 Subject: [PATCH] added support for protect and currying (lambda functor return types) [SVN r12138] --- .../lambda/detail/return_type_traits.hpp | 266 +++++++++++++----- 1 file changed, 201 insertions(+), 65 deletions(-) diff --git a/include/boost/lambda/detail/return_type_traits.hpp b/include/boost/lambda/detail/return_type_traits.hpp index acf6cce..990dfe9 100644 --- a/include/boost/lambda/detail/return_type_traits.hpp +++ b/include/boost/lambda/detail/return_type_traits.hpp @@ -71,8 +71,133 @@ template struct return_type_1 { detail::return_type_deduction_failure type; }; + // read the comments for return_type_2_0 +template struct return_type_1_0 { + +typedef typename boost::remove_reference::type A1; + + typedef typename + detail::IF_type< + boost::is_function::value, + boost::add_reference, + boost::add_const + >::type A2; + +typedef typename + detail::IF< + is_lambda_functor::value, + lambda_functor_sub< + lambda_functor_args< + action<1, Act>, + tuple, + dig_arity::value + > + >, + typename return_type_1::type + >::RET type; +}; + // binary actions --------------------------------------------------- -template struct return_type_2; + template struct return_type_2; + +// experimental feature + // We may have a lambda functor as a result type of a subexpression + // (if protect) has been used. + // Thus, if one of the parameter types is a lambda functor, the result + // is a lambda functor as well. + // We need to make a conservative choise here, all arguments in the + // resulting lambda functor will be stored as const copies. The true + // result type may have non-const reference arguments, but it is either + // impossible or very hard to find out that. And references here might + // be unsafe (references to temporaries that do not exist). + + // The return type is a subclass of lambda_functor, which has a converting + // copy constructor. It can copy any lambda functor, that has the same + // action type and code, and a copy compatible argument tuple. + +template struct return_type_2_0 { + + typedef typename boost::remove_reference::type A1; + typedef typename boost::remove_reference::type B1; + + // adding const to a function type fails, these tests are to + // avoid that. Note that only the true branch is instantiated with this IF + typedef typename + detail::IF_type< + boost::is_function::value, + boost::add_reference, + boost::add_const + >::type A2; + + typedef typename + detail::IF_type< + boost::is_function::value, + boost::add_reference, + boost::add_const + >::type B2; + + +typedef typename + detail::IF< + is_lambda_functor::value || is_lambda_functor::value, + lambda_functor_sub< + lambda_functor_args< + action<2, Act>, + tuple, + combine_arities::value + > + >, + typename return_type_2::type + >::RET type; +}; + + // Was needed for a while, not now, since no return type deduction depends + // on more than two arguments + +// template struct return_type_3_0 { + +// typedef typename boost::remove_reference::type A1; +// typedef typename boost::remove_reference::type B1; +// typedef typename boost::remove_reference::type C1; + +// // adding const to a function type fails, these tests are to +// // avoid that. Note that only the true branch is instantiated with this IF +// typedef typename +// detail::IF_type< +// boost::is_function::value, +// boost::add_reference, +// boost::add_const +// >::type A2; + +// typedef typename +// detail::IF_type< +// boost::is_function::value, +// boost::add_reference, +// boost::add_const +// >::type B2; + +// typedef typename +// detail::IF_type< +// boost::is_function::value, +// boost::add_reference, +// boost::add_const +// >::type C2; + + +// typedef typename +// detail::IF< +// is_lambda_functor::value || is_lambda_functor::value || +// is_lambda_functor::value, +// lambda_functor_sub< +// lambda_functor_args< +// action<3, Act>, +// tuple, +// combine_arities::value +// > +// >, +// typename return_type_1::type +// >::RET type; +// }; // unary function action (it is binary action) // If a function object overloads operator(), the return type could depend @@ -165,23 +290,20 @@ struct return_type_1, A > { template struct return_type, Args, Code>, Open> { typedef -// typename detail::constify_rvalues< - typename return_type_1< + typename return_type_1_0< Act, typename return_type< typename detail::tuple_element_as_reference< 0, Args >::type, Open>::type >::type -// >::type type; }; template struct return_type, Args, Code>, Open> { typedef -// typename detail::constify_rvalues< - typename return_type_2< + typename return_type_2_0< Act, typename return_type< typename detail::tuple_element_as_reference<0, Args>::type, @@ -192,60 +314,32 @@ struct return_type, Args, Code>, Open> { Open >::type >::type -// >::type type; }; -// unary to 3-ary lambda_functor_actions -template -struct return_type >, Args, Code>, Open> { + // Was needed for a while, not now, since no return type deduction depends + // on more than two arguments -// first call recursively return_type again. There can be arbitrary -// many nested lambda_functors with lambda_functor_action, -// this traverses them all. - typedef typename - return_type< - typename detail::tuple_element_as_reference<0,Args>::type, Open - >::type type_1; - -// type_1 must be something that can be called (it must be bindable), -// hence we can use function_adaptor to dig out its return type. - typedef typename - function_adaptor< - typename detail::remove_reference_and_cv::type - >::result_type type; -}; - -template -struct return_type >, Args, Code>, Open> { - typedef typename return_type< - typename detail::tuple_element_as_reference<0,Args>::type, Open - >::type type_1; - typedef typename function_adaptor< - typename detail::remove_reference_and_cv::type - >::result_type type; -}; - - -template -struct return_type >, Args, Code>, Open> { - typedef typename return_type< - typename detail::tuple_element_as_reference<0,Args>::type, Open - >::type type_1; - typedef typename function_adaptor< - typename detail::remove_reference_and_cv::type - >::result_type type; -}; - -template -struct return_type >, Args, Code>, Open> { - typedef typename return_type< - typename detail::tuple_element_as_reference<0,Args>::type, Open - >::type type_1; - typedef typename function_adaptor< - typename detail::remove_reference_and_cv::type - >::result_type type; -}; +// template +// struct return_type, Args, Code>, Open> { +// typedef +// typename return_type_3_0< +// Act, +// typename return_type< +// typename detail::tuple_element_as_reference<0, Args>::type, +// Open +// >::type, +// typename return_type< +// typename detail::tuple_element_as_reference<1, Args>::type, +// Open +// >::type, +// typename return_type< +// typename detail::tuple_element_as_reference<2, Args>::type, +// Open +// >::type +// >::type +// type; +// }; // protect action: @@ -255,6 +349,43 @@ struct return_type, Args, Code>, O typedef typename detail::tuple_element_as_reference<0,Args>::type type; }; +// curry action: +template +struct return_type >, + Args, Code>, Open> { + // take one stored argument type and push it to the open args + typedef typename + return_type< + typename boost::tuples::element<0,Args>::type, + open_args::type, + typename Open::type1, + typename Open::type2> >::type + type; +}; + +template +struct return_type >, Args, Code>, Open> { + // take one stored argument type and push it to the open args + typedef typename + return_type::type, + open_args::type, + typename Open::type1, + typename Open::type2> >::type + type; +}; +template +struct return_type >, Args, Code>, Open> { + // take two stored arguments type and push them to the open args + typedef typename + return_type::type, + open_args::type, + typename boost::tuples::element<2,Args>::type, + typename Open::type1> >::type + type; +}; + + + // 3 arguments or more --------------------------------------------- @@ -267,41 +398,46 @@ struct return_type, Args, Code>, O template struct return_type, Args, Code>, Open> { typedef -// typename detail::constify_rvalues< - typename return_type_1< + typename return_type_1_0< Act, typename return_type< typename detail::tuple_element_as_reference<0,Args>::type, Open >::type >::type -// >::type type; }; // The explicit return type action case, it is unary template -struct return_type >, Args, Code>, Open> { - typedef //typename detail::constify_rvalues::type - RET type; +struct return_type< + lambda_functor_args< + action<1, explicit_return_type_action >, + Args, + Code>, + Open> { + typedef RET type; }; // return types of control constructs (all return void) template -struct return_type >, Args, Code>, Open > +struct return_type >, + Args, Code>, Open > { typedef void type; }; template -struct return_type >, Args, Code>, Open > +struct return_type >, + Args, Code>, Open > { typedef void type; }; template -struct return_type >, Args, Code>, Open > +struct return_type >, + Args, Code>, Open > { typedef void type; };