diff --git a/include/boost/lambda/detail/actions.hpp b/include/boost/lambda/detail/actions.hpp index 413488c..55f2cf3 100644 --- a/include/boost/lambda/detail/actions.hpp +++ b/include/boost/lambda/detail/actions.hpp @@ -22,9 +22,8 @@ namespace boost { namespace lambda { -template struct action; - +template struct action; // these need to be defined here, since the corresponding lambda // functions are members of lambda_functor classes @@ -172,6 +171,27 @@ public: } }; + // actions, for which the existence of protect is checked in return type + // deduction. +class protectable {}; + +namespace detail { +template struct is_protectable_action { + BOOST_STATIC_CONSTANT(bool, value = (boost::is_base_and_derived::value)); +}; + +template<> struct is_protectable_action > { + BOOST_STATIC_CONSTANT(bool, value = true); + }; +template<> struct is_protectable_action > { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + +} // end detail + + + + } // namespace lambda } // namespace boost diff --git a/include/boost/lambda/detail/arity_code.hpp b/include/boost/lambda/detail/arity_code.hpp index b29a095..6da4640 100644 --- a/include/boost/lambda/detail/arity_code.hpp +++ b/include/boost/lambda/detail/arity_code.hpp @@ -45,6 +45,12 @@ template struct dig_arity; namespace detail { + +template struct reduce_arity +{ + BOOST_STATIC_CONSTANT(int, value = Arity >> Step); +}; + // The implementation template, do not instantiate this directly template struct dig_arity_ { static const int value = NONE; diff --git a/include/boost/lambda/detail/function_adaptors.hpp b/include/boost/lambda/detail/function_adaptors.hpp index 088ddbc..2c2e1c5 100644 --- a/include/boost/lambda/detail/function_adaptors.hpp +++ b/include/boost/lambda/detail/function_adaptors.hpp @@ -513,28 +513,71 @@ struct function_adaptor struct get_result_type { - typedef typename T::result_type type; +template struct get_result_type { + typedef typename F::result_type type; }; +template class get_sig_result_type { + typedef typename Args::head_type Func; + typedef typename detail::remove_reference_and_cv::type plainF; +public: + // To sig we pass a cons list, where the head is the function object type + // itself (potentially cv-qualified, but not a reference type) + // and the tail contains the types of the actual arguments to be passed + // to the function object. The arguments are reference types + typedef typename plainF::template sig::type type; +}; + + +// check for a member typedef return_type or an member class template sig +template class get_functor_result_type { + typedef typename Args::head_type Func; + typedef typename boost::remove_cv::type plain_F; +public: + // if the function object inherits from has_sig, we check for sig + // otherwise for result_type typedef + typedef + detail::IF_type< + boost::is_base_and_derived::value, + detail::get_sig_result_type, + detail::get_result_type + >::type type; +}; + + } // end detail -template class function_adaptor_sub : - public function_adaptor { - typedef typename function_adaptor::type type1; +template +class function_adaptor_with_actuals //: public +// function_adaptor::type> +{ + typedef typename Args::head_type Func; + typedef typename boost::remove_reference::type non_ref_Func; + typedef typename boost::remove_cv::type plain_Func; + typedef typename function_adaptor::type type1; + public: typedef typename detail::IF_type< boost::is_same::value, - detail::get_result_type, // it's ok to try this - function_adaptor + detail::get_functor_result_type< + boost::tuples::cons + >, // it's ok to try this (an arbitrary func. object) + function_adaptor + // Here we know Func's ret type + // (func is a member function or function pointer/reference) >::type type; }; @@ -546,3 +589,4 @@ public: #endif + diff --git a/include/boost/lambda/detail/lambda_functors.hpp b/include/boost/lambda/detail/lambda_functors.hpp index 9b32ff2..c6a6924 100644 --- a/include/boost/lambda/detail/lambda_functors.hpp +++ b/include/boost/lambda/detail/lambda_functors.hpp @@ -95,10 +95,97 @@ BOOST_LAMBDA_LAMBDA_FUNCTOR_SUBSCRIPT }; +namespace detail { + + // helpers +template struct identity { typedef T type; }; + + // take the Nth element in the tuple, or null_type if tuple is not + // long enough + +template +struct element_or_null_type { + typedef typename + detail::IF_type< + (N < boost::tuples::length::value), + boost::tuples::element, + identity + >::type type; +}; + + // Lambda functors all provide the sig member template for + // querying their return type. + // these type mappings implement the tools for that deduction + + //type mapping to compute the new lambda functor resulting from a curried + // call. + template + struct curry_sig { + + // First arg in SigArgs is the lambda functor type, that's why the -1 + BOOST_STATIC_CONSTANT(int, acount = boost::tuples::length::value-1); + + + // currying is only supported for 2- and 3-ary lambda functors, and + // must be called by 1 or 2 arguments. + // BOOST_STATIC_ASSERT(acount == 1 || acount == 2); + // BOOST_STATIC_ASSERT(dig_arity::value == SECOND || dig_arity::value == THIRD); + + + typedef typename detail::element_or_null_type<1, SigArgs>::type el_1; + typedef typename detail::element_or_null_type<2, SigArgs>::type el_2; + + typedef lambda_functor< + lambda_functor_args< + action >, + // remoce_const_refernce takes care that const null_type will + // be null_type, that arrays are always stored as const refs, + // that nonconst refs remain nonconst refs, and everything else goes + // to const copy. + + tuple< + LF, + typename detail::remove_const_reference::type, + typename detail::remove_const_reference::type + >, + detail::reduce_arity::value, acount>::value + > + > type; + }; + + // enter the normal return type deduction + template + struct eval_sig + { + typedef typename + return_type< + LF, + open_args< + detail::element_or_null_type<1, SigArgs>::type, + detail::element_or_null_type<2, SigArgs>::type, + detail::element_or_null_type<3, SigArgs>::type + > + >::type type; + }; + + // either a normal evaluation, or a curried call + template + struct lambda_functor_sig + { + typedef typename + detail::IF_type< + (boost::tuples::length::value - 1 < Args_expected), + detail::curry_sig, + detail::eval_sig + >::type type; + }; + +} // end detail + // -- lambda_functor NONE ------------------------------------------------ template class lambda_functor > - : public lambda_functor_base + : public lambda_functor_base, public has_sig { public: typedef lambda_functor_base inherited; @@ -112,7 +199,11 @@ public: (const lambda_functor >& f) : inherited(f.args) {} - typename + template struct sig { + typedef typename + detail::lambda_functor_sig::type type; + }; + return_type< lambda_functor, open_args @@ -155,6 +246,11 @@ public: (const lambda_functor >& f) : inherited(f.args) {} + template struct sig { + typedef typename + detail::lambda_functor_sig::type type; + }; + template typename return_type >::type @@ -181,7 +277,7 @@ public: // -- lambda_functor SECOND ------------------------------------------------- template class lambda_functor > - : public lambda_functor_base + : public lambda_functor_base, public has_sig { public: typedef lambda_functor_base inherited; @@ -195,6 +291,12 @@ public: (const lambda_functor >& f) : inherited(f.args) {} + + template struct sig { + typedef typename + detail::lambda_functor_sig::type type; + }; + template typename return_type >::type operator()(A& a, B& b) const @@ -207,24 +309,28 @@ public: // currying call: creates another lambda functor template - lambda_functor< - lambda_functor_args< - action<3, curry_action<1> >, - detail::bind_tuple_mapper::type, - FIRST - > - > + sig >::type +// 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) + typename sig >::type +// lambda_functor< +// lambda_functor_args< +// action<3, curry_action<1> >, +// detail::bind_tuple_mapper::type, +// FIRST +// > +// > + ( + tuple::type>(*this, a) ); } @@ -241,7 +347,7 @@ public: // -- lambda_functor THIRD ------------------------------------------------- template -class lambda_functor > : public lambda_functor_base +class lambda_functor > : public lambda_functor_base, public has_sig { public: typedef lambda_functor_base inherited; @@ -255,6 +361,11 @@ public: (const lambda_functor >& f) : inherited(f.args) {} + template struct sig { + typedef typename + detail::lambda_functor_sig::type type; + }; + template typename return_type >::type operator()(A& a, B& b, C& c) const @@ -270,49 +381,56 @@ public: // currying call, one argument still missing template - lambda_functor< - lambda_functor_args< - action<4, curry_action<2> >, - detail::bind_tuple_mapper::type, - FIRST - > - > + sig >::type +// 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) + typename sig >::type +// lambda_functor< +// lambda_functor_args< +// action<4, curry_action<2> >, +// detail::bind_tuple_mapper::type, +// FIRST +// > +// > + ( tuple< + lambda_functor, + typename detail::remove_const_reference::type, + typename detail::remove_const_reference::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 - > - > + sig >::type +// 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) + typename sig >::type +// lambda_functor< +// lambda_functor_args< +// action<4, curry_action<1> >, +// detail::bind_tuple_mapper::type, +// SECOND +// > +// > + ( + tuple::type>(*this, a) ); } diff --git a/include/boost/lambda/detail/lambda_traits.hpp b/include/boost/lambda/detail/lambda_traits.hpp index 80d4bb7..834bb9e 100644 --- a/include/boost/lambda/detail/lambda_traits.hpp +++ b/include/boost/lambda/detail/lambda_traits.hpp @@ -228,6 +228,10 @@ struct parameter_traits_, Any >{ typedef T& type; }; +template +struct parameter_traits_ { + typedef void type; +}; } // end namespace detail @@ -270,6 +274,10 @@ struct const_copy_argument { typedef typename detail::generate_error::references_not_allowed type; }; +template<> +struct const_copy_argument { + typedef void type; +}; // The default is non-const reference ------------------------- @@ -308,6 +316,11 @@ struct reference_argument > { typedef lambda_functor type; }; +template<> +struct reference_argument { + typedef void type; +}; + namespace detail { // Array to pointer conversion @@ -337,7 +350,7 @@ struct array_to_pointer { // --------------------------------------------------------------------------- // The call_traits for bind -// Honours the reference_wrapper class. +// Respects the reference_wrapper class. // These templates are used outside of bind functions as well. // the bind_tuple_mapper provides a shorter notation for default @@ -414,6 +427,11 @@ struct bind_traits >{ typedef T& type; }; +template<> +struct bind_traits { + typedef void type; +}; + template < @@ -436,6 +454,17 @@ struct bind_tuple_mapper { typename bind_traits::type> type; }; +// bind_traits, except map const T& -> const T + // this is needed e.g. in currying. Const reference arguments can + // refer to temporaries, so it is not safe to store them as references. + template struct remove_const_reference { + typedef typename bind_traits::type type; + }; + + template struct remove_const_reference { + typedef const T type; + }; + // maps the bind argument types to the resulting lambda functor type template < diff --git a/include/boost/lambda/detail/operator_actions.hpp b/include/boost/lambda/detail/operator_actions.hpp index cb9c743..8892f56 100644 --- a/include/boost/lambda/detail/operator_actions.hpp +++ b/include/boost/lambda/detail/operator_actions.hpp @@ -19,6 +19,7 @@ namespace boost { namespace lambda { + // -- artihmetic ---------------------- class plus_action {}; @@ -89,7 +90,7 @@ template class post_increment_decrement_action; #endif #define BOOST_LAMBDA_BINARY_ACTION(OPER_SYMBOL, GROUP, OPER_NAME) \ -template<> class GROUP < OPER_NAME> {\ +template<> class GROUP < OPER_NAME> : public protectable {\ public: \ template\ static RET apply(A& a, B& b) { \ @@ -135,7 +136,7 @@ BOOST_LAMBDA_BINARY_ACTION(^=,bitwise_assignment_action,xor_action) BOOST_LAMBDA_BINARY_ACTION(=,other_action, assignment_action) // subscript is done directly because BOOST_LAMBDA_BINARY_ACTION currently doesn't handle it. -template<> class other_action { +template<> class other_action : public protectable { public: template static RET apply(A& a, B& b) { return a[b]; } @@ -157,7 +158,7 @@ public: #endif #define BOOST_LAMBDA_PREFIX_UNARY_ACTION(OPER_SYMBOL, GROUP, OPER_NAME) \ -template<> class GROUP {\ +template<> class GROUP : public protectable {\ public: \ template\ static RET apply(A& a) { return OPER_SYMBOL a; }\ @@ -181,7 +182,7 @@ BOOST_LAMBDA_PREFIX_UNARY_ACTION( , other_action, identity_action) #endif #define BOOST_LAMBDA_POSTFIX_UNARY_ACTION(OPER_SYMBOL, GROUP, OPER_NAME) \ -template<> class GROUP {\ +template<> class GROUP : public protectable {\ public: \ template\ static RET apply(A& a) { return a OPER_SYMBOL; }\ diff --git a/include/boost/lambda/detail/ret.hpp b/include/boost/lambda/detail/ret.hpp index 84c80a3..a7d0f04 100644 --- a/include/boost/lambda/detail/ret.hpp +++ b/include/boost/lambda/detail/ret.hpp @@ -176,7 +176,7 @@ public: // functor for one application, unlambda for good. template -class non_lambda_functor { +class non_lambda_functor : public has_sig { lambda_functor lf; // a lambda functor public: @@ -184,32 +184,42 @@ public: // 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; +// typedef typename +// return_type >::type +// result_type; + + + template struct sig { + typedef typename + lambda_functor::template sig::type type; + }; non_lambda_functor(const lambda_functor& a) : lf(a) {} - result_type operator()() const { - return lf.template ret_call(); + sig > >::type + operator()() const { + return lf.template ret_call > >::type>(); } template - result_type operator()(A& a) const { - return lf.template ret_call(a); + sig, A&> >::type + operator()(A& a) const { + return lf.template ret_call, A&> >::type >(a); } template - result_type operator()(A& a, B& b) const { - return lf.template ret_call(a, b); + sig, A&, B&> >::type + operator()(A& a, B& b) const { + return lf.template ret_call, A&, B&> >::type >(a, b); } template - result_type operator()(A& a, B& b, C& c) const { - return lf.template ret_call(a, b, c); + sig, A&, B&, C&> >::type + operator()(A& a, B& b, C& c) const { + return lf.template ret_call, A&, B&, C&> >::type>(a, b, c); } }; diff --git a/include/boost/lambda/detail/return_type_traits.hpp b/include/boost/lambda/detail/return_type_traits.hpp index 1ba4be9..603feb8 100644 --- a/include/boost/lambda/detail/return_type_traits.hpp +++ b/include/boost/lambda/detail/return_type_traits.hpp @@ -35,7 +35,7 @@ namespace lambda { // So, in the case the return type deduction should fail, it should not // fail directly, but rather result in a valid but wrong return type, - // causing a compile time error, if the function is really called. + // causing a compile time error only if the function is really called. namespace detail { @@ -67,6 +67,13 @@ struct return_type { typedef Arg type; }; + + // different arities: +template class return_type_1; // 1-ary actions +template class return_type_2; // 2-ary +template class return_type_N; // >3- ary + + // Unary actions (result from unary operators) // do not have a default return type. template struct return_type_1 { @@ -74,30 +81,50 @@ 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; + // read the comments for return_type_2_protect + +namespace detail { + +template +class protect_conversion { + + // T -> const T + // T& -> T& + // const T& -> const T + // function& -> function& + // const array& -> const array& + // lambda functors are not stored as references + // function reference types are function reference types + typedef typename boost::remove_reference::type A1; + + typedef typename detail::IF< + boost::is_reference::value + && !boost::is_const::value + && !is_lambda_functor::value, + A, + const_copy_argument::type // handles funtion and array type correctly + >::RET type; +}; + +} // end detail + +template struct return_type_1_protect { typedef typename detail::IF< - is_lambda_functor::value, + is_lambda_functor::value, lambda_functor< lambda_functor_args< action<1, Act>, - tuple, + tuple::type>, dig_arity::value > >, typename return_type_1::type >::RET type; + }; // binary actions --------------------------------------------------- @@ -108,36 +135,41 @@ typedef typename // (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). + // We need to make a conservative choise here. + // The resulting lambda functor stores all const reference arguments as + // const copies. References to non-const are stored as such. + // So if the source of the argument is an const open argument, a bound + // argument stroed as a const reference, or a function returning a + // const reference, that information is lost. There is no way of + // telling apart 'real const references' from just 'LL internal + // const references' (or it would be really hard) // 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; +template struct return_type_2_protect { - typedef typename - detail::IF_type< - boost::is_function::value, - boost::add_reference, - boost::add_const - >::type B2; +// 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< +// !is_lambda_functor::value && (boost::is_function::value || !(boost::is_const::value)), +// boost::add_reference, +// boost::add_const +// >::type A2; + +// typedef typename +// detail::IF_type< +// !is_lambda_functor::value && ( boost::is_function::value || !(boost::is_const::value)), +// boost::add_reference, +// boost::add_const +// >::type B2; typedef typename @@ -146,7 +178,8 @@ typedef typename lambda_functor< lambda_functor_args< action<2, Act>, - tuple, + tuple::type, + typename detail::protect_conversion::type>, combine_arities::value > >, @@ -154,61 +187,17 @@ typedef typename >::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< -// 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 +// // on the argument types. This is not taken into consideration. +// template +// struct return_type_2, A, B> { +// typedef typename return_type_1, A>::type type; // }; -// unary function action (it is binary action) -// If a function object overloads operator(), the return type could depend -// on the argument types. This is not taken into consideration. -template -struct return_type_2, A, B> { - typedef typename return_type_1, A>::type type; -}; // reduce to lambda_functor_args // to be on the safe side, constness and references are stripped away, @@ -275,20 +264,66 @@ struct return_type, Open> { // on the argument types. This is not taken into consideration. // use the return type given in the bind invocation as bind(...) -template -struct return_type_1, A > { +template +struct return_type_1, A > { + typedef Ret type; +}; +template +struct return_type_2, A, B > { + typedef Ret type; +}; +template +struct return_type_N, Args> { typedef Ret type; }; // Ret is detail::unspecified, so try to deduce return type -template -struct return_type_1, A > { - typedef typename function_adaptor_sub< - typename detail::remove_reference_and_cv::type - >::type type; +template +struct return_type_1, A > { + typedef typename function_adaptor_with_actuals::inherited>::type type; +}; +template +struct return_type_2, A, B > { + typedef typename function_adaptor_with_actuals::inherited>::type type; +}; +template +struct return_type_N, Args > { + typedef typename function_adaptor_with_actuals::type type; }; +namespace detail { + +template +struct map_to_return_types { + typedef typename return_type< + typename boost::tuples::access_traits::const_type, + Open + >::type ret_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 ref_to_const_ret_type; + + typedef boost::tuples::cons< + ref_to_const_ret_type, + typename map_to_return_types::type + > type; +}; + +template +struct map_to_return_types { + typedef boost::tuples::null_type type; +}; + +} // end detail + // general unary and binary actions template struct return_type, Args, Code>, Open> { @@ -309,7 +344,12 @@ struct return_type, Args, Code>, Open> { public: - typedef typename return_type_1_0::type type; + typedef typename + detail::IF_type< + detail::is_protectable_action::value, + return_type_1_protect, + return_type_1 + >::type type; }; @@ -334,38 +374,103 @@ class return_type, Args, Code>, Open> { >::type refc_B_type; public: - typedef typename return_type_2_0::type type; + typedef typename + detail::IF_type< + detail::is_protectable_action::value, + return_type_2_protect, + return_type_2 + >::type type; + }; - // Was needed for a while, not now, since no return type deduction depends - // on more than two arguments + // This is the general case. Will match any action with arity >= 3 +template +class return_type, Args, Code>, Open> { + typedef typename detail::map_to_return_types::type actual_args; +public: + typedef typename return_type_N::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; +// 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 return_type< +// typename detail::tuple_element_as_reference<2, Args>::type, +// Open +// >::type C_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; +// typedef typename boost::add_reference< +// typename boost::add_const::type +// >::type refc_C_type; + +// public: +// // no 3- or higher ary protectable actions exist, no need to check +// typedef typename return_type_3::type type; // }; +// // 4 args or more (must be a function action) +// 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; + +// typedef typename return_type< +// typename detail::tuple_element_as_reference<2, Args>::type, +// Open +// >::type C_type; + +// typedef typename return_type< +// typename detail::tuple_element_as_reference<3, Args>::type, +// Open +// >::type D_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; +// typedef typename boost::add_reference< +// typename boost::add_const::type +// >::type refc_C_type; +// typedef typename boost::add_reference< +// typename boost::add_const::type +// >::type refc_D_type; + +// public: +// typedef typename return_type_4::type 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 +// note, that return_type_2_protect is still called, so user can overload // return_type_2 for user defined types. template @@ -383,7 +488,7 @@ class return_type >, Ar public: typedef typename - return_type_2_0, A_type, B_type>::type type; + return_type_2_protect, A_type, B_type>::type type; }; // protect action: @@ -432,31 +537,31 @@ struct return_type >, Args, Code>, -// 3 arguments or more --------------------------------------------- -// this must be a function_action. Note that the previous unary and binary -// specalisations take care of nullary and unary function adaptors, that is, -// unary and binary actions. -// Since function_actions determine the return type based on the function -// object only, we can ignore the arguments and reuse return_type_1. +// // 3 arguments or more --------------------------------------------- +// // this must be a function_action. Note that the previous unary and binary +// // specalisations take care of nullary and unary function adaptors, that is, +// // unary and binary actions. +// // Since function_actions determine the return type based on the function +// // object only, we can ignore the arguments and reuse return_type_1. -template -class return_type, Args, Code>, Open> { +// 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<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; +// // 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: +// public: - typedef typename return_type_1_0::type type; -}; +// typedef typename return_type_1_protect::type type; +// }; // The explicit return type action case, it is unary template @@ -486,6 +591,13 @@ struct return_type >, typedef void type; }; +template +struct return_type >, + Args, Code>, Open > +{ + typedef void type; +}; + template struct return_type >, Args, Code>, Open >