diff --git a/include/boost/lambda/detail/return_type_traits.hpp b/include/boost/lambda/detail/return_type_traits.hpp index 1a8b5f0..1ba4be9 100644 --- a/include/boost/lambda/detail/return_type_traits.hpp +++ b/include/boost/lambda/detail/return_type_traits.hpp @@ -292,32 +292,49 @@ struct return_type_1, A > { // general unary and binary actions template struct return_type, Args, Code>, Open> { - typedef - typename return_type_1_0< - Act, - typename return_type< - typename detail::tuple_element_as_reference< - 0, Args - >::type, Open>::type - >::type - type; + + typedef typename return_type< + typename detail::tuple_element_as_reference<0, Args>::type, + Open + >::type A_type; + + // const and reference is added, so that specializations for return_type_1 + // become easier (we can rely on the Args always being references, so the + // number of specializations doesn't explode. + // Note! If T is already a reference to nonconst, it will remain that way + // To return type deduction, const T& is the same as rvalue T + typedef typename boost::add_reference< + typename boost::add_const::type + >::type refc_A_type; + +public: + + typedef typename return_type_1_0::type type; + }; template -struct return_type, Args, Code>, Open> { - typedef - typename return_type_2_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 - >::type - type; +class return_type, Args, Code>, Open> { + + typedef typename return_type< + typename detail::tuple_element_as_reference<0, Args>::type, + Open + >::type A_type; + + typedef typename return_type< + typename detail::tuple_element_as_reference<1, Args>::type, + Open + >::type B_type; + + typedef typename boost::add_reference< + typename boost::add_const::type + >::type refc_A_type; + typedef typename boost::add_reference< + typename boost::add_const::type + >::type refc_B_type; + +public: + typedef typename return_type_2_0::type type; }; // Was needed for a while, not now, since no return type deduction depends @@ -344,6 +361,30 @@ struct return_type, Args, Code>, Open> { // type; // }; + +// special case for comma action: +// As the return type needs to be exactly the type of the rightmost argument, +// we cannot add a const and reference (we need to preserve rvalueness) +// note, that return_type_2_0 is still called, so user can overload +// return_type_2 for user defined types. + +template +class return_type >, Args, Code>, Open> { + + typedef typename return_type< + typename detail::tuple_element_as_reference<0, Args>::type, + Open + >::type A_type; + + typedef typename return_type< + typename detail::tuple_element_as_reference<1, Args>::type, + Open + >::type B_type; + +public: + typedef typename + return_type_2_0, A_type, B_type>::type type; +}; // protect action: // the return type is the lambda_functor wrapped inside protect @@ -399,16 +440,22 @@ struct return_type >, Args, Code>, // object only, we can ignore the arguments and reuse return_type_1. template -struct return_type, Args, Code>, Open> { - typedef - typename return_type_1_0< - Act, - typename return_type< - typename detail::tuple_element_as_reference<0,Args>::type, - Open - >::type - >::type - type; +class return_type, Args, Code>, Open> { + + typedef typename return_type< + typename detail::tuple_element_as_reference<0, Args>::type, + Open + >::type A_type; + + // reference is added, so that specializations for return_type_1 + // become easier. + typedef typename boost::add_reference< + typename boost::add_const::type + >::type refc_A_type; + +public: + + typedef typename return_type_1_0::type type; }; // The explicit return type action case, it is unary @@ -418,7 +465,8 @@ struct return_type< action<1, explicit_return_type_action >, Args, Code>, - Open> { + Open> +{ typedef RET type; };