From 8eda5d32cabeb008e622532aee84f413f4e7218b Mon Sep 17 00:00:00 2001 From: Tobias Schwinger Date: Thu, 12 Jul 2007 09:08:46 +0000 Subject: [PATCH] completes boost::result_of-based result type computation [SVN r38194] --- .../detail/Attic/nullary_call_base.hpp | 94 +++++++++++++++---- .../boost/fusion/functional/adapter/fused.hpp | 35 ++++--- .../adapter/fused_function_object.hpp | 27 ++++-- .../functional/adapter/fused_procedure.hpp | 37 ++++---- .../fusion/functional/adapter/limits.hpp | 3 + .../functional/adapter/unfused_generic.hpp | 48 +++++++--- .../adapter/unfused_lvalue_args.hpp | 49 ++++++---- .../adapter/unfused_rvalue_args.hpp | 48 +++++++--- .../functional/adapter/unfused_typed.hpp | 66 ++++++++----- test/functional/make_unfused_generic.cpp | 6 +- test/functional/make_unfused_lvalue_args.cpp | 6 +- test/functional/make_unfused_rvalue_args.cpp | 6 +- test/functional/unfused_generic.cpp | 18 ++-- test/functional/unfused_lvalue_args.cpp | 8 +- test/functional/unfused_rvalue_args.cpp | 6 +- test/functional/unfused_typed.cpp | 4 +- 16 files changed, 305 insertions(+), 156 deletions(-) diff --git a/include/boost/fusion/functional/adapter/detail/Attic/nullary_call_base.hpp b/include/boost/fusion/functional/adapter/detail/Attic/nullary_call_base.hpp index c089a697..cd8383ae 100644 --- a/include/boost/fusion/functional/adapter/detail/Attic/nullary_call_base.hpp +++ b/include/boost/fusion/functional/adapter/detail/Attic/nullary_call_base.hpp @@ -26,43 +26,101 @@ namespace boost { namespace fusion { namespace detail template struct get_result_spec { - typedef typename remove_const::type>::type function; - typedef typename function::template result type; + private: + typedef typename boost::remove_const< + typename boost::remove_reference::type>::type function; + + typedef fusion::vector0 arg; + public: + typedef typename function::template result call_0_result; + typedef typename function::template result + call_const_0_result; }; - template ::type>::value> + template ::call_const_0_result>::value, + bool Enable = detail::has_type< + typename get_result_spec::call_0_result>::value> struct nullary_call_base { - template inline void operator()(T reserved::*) const { } protected: - typedef boost::blank r0; - }; + typedef typename get_result_spec::call_const_0_result + call_const_0_result_class; - template - struct nullary_call_base - { - private: - typedef typename remove_const::type>::type function; - protected: - typedef typename function::template result r0; + typedef typename get_result_spec::call_0_result + call_0_result_class; public: + typedef typename call_const_0_result_class::type + call_const_0_result; - inline typename r0::type - operator()() const + inline call_const_0_result operator()() const { fusion::vector0 arg; return static_cast(this)->fnc_transformed(arg); } - inline typename r0::type - operator()() + typedef typename get_result_spec::call_0_result::type + call_0_result; + + inline call_0_result operator()() { fusion::vector0 arg; return static_cast(this)->fnc_transformed(arg); } }; + template + struct nullary_call_base + { + protected: + typedef typename get_result_spec::call_const_0_result + call_const_0_result_class; + + typedef typename boost::blank call_0_result_class; + public: + typedef typename call_const_0_result_class::type + call_const_0_result, call_0_result; + + inline call_const_0_result operator()() const + { + fusion::vector0 arg; + return static_cast(this)->fnc_transformed(arg); + } + }; + + template + struct nullary_call_base + { + protected: + typedef typename boost::blank call_const_0_result_class; + + typedef typename get_result_spec::call_0_result + call_0_result_class; + public: + typedef void call_const_0_result; + typedef typename call_0_result_class::type call_0_result; + + inline call_const_0_result operator()() + { + fusion::vector0 arg; + return static_cast(this)->fnc_transformed(arg); + } + }; + + template + struct nullary_call_base + { + protected: + typedef boost::blank call_0_result_class; + typedef boost::blank call_const_0_result_class; + public: + typedef void call_0_result; + typedef void call_const_0_result; + + template inline void operator()(T reserved::*) const { } + }; + }}} #endif diff --git a/include/boost/fusion/functional/adapter/fused.hpp b/include/boost/fusion/functional/adapter/fused.hpp index 31947392..40096643 100644 --- a/include/boost/fusion/functional/adapter/fused.hpp +++ b/include/boost/fusion/functional/adapter/fused.hpp @@ -35,40 +35,47 @@ namespace boost { namespace fusion { } template - inline typename result_of::invoke::type + inline typename result_of::invoke::type operator()(Seq const & s) const { - return fusion::invoke(this->fnc_transformed,s); + return fusion::invoke(this->fnc_transformed,s); } template - inline typename result_of::invoke::type + inline typename result_of::invoke::type operator()(Seq const & s) { - return fusion::invoke(this->fnc_transformed,s); + return fusion::invoke(this->fnc_transformed,s); } template - inline typename result_of::invoke::type + inline typename result_of::invoke::type operator()(Seq & s) const { - return fusion::invoke(this->fnc_transformed,s); + return fusion::invoke(this->fnc_transformed,s); } template - inline typename result_of::invoke::type + inline typename result_of::invoke::type operator()(Seq & s) { - return fusion::invoke(this->fnc_transformed,s); + return fusion::invoke(this->fnc_transformed,s); } - template - struct result; - - template - struct result(Seq)> - : result_of::invoke + template + struct result { }; + + template + struct result< Self const (Seq) > + : result_of::invoke + { }; + + template + struct result< Self(Seq) > + : result_of::invoke + { }; + }; }} diff --git a/include/boost/fusion/functional/adapter/fused_function_object.hpp b/include/boost/fusion/functional/adapter/fused_function_object.hpp index a73ad837..b7d176d1 100644 --- a/include/boost/fusion/functional/adapter/fused_function_object.hpp +++ b/include/boost/fusion/functional/adapter/fused_function_object.hpp @@ -35,16 +35,16 @@ namespace boost { namespace fusion { } template - inline typename result_of::invoke_function_object::type operator()(Seq const & s) const + inline typename result_of::invoke_function_object::type operator()(Seq const & s) const { return fusion::invoke_function_object< func_const_fwd_t >(this->fnc_transformed,s); } template - inline typename result_of::invoke_function_object::type + inline typename result_of::invoke_function_object::type operator()(Seq const & s) { return fusion::invoke_function_object< @@ -52,7 +52,8 @@ namespace boost { namespace fusion } template - inline typename result_of::invoke_function_object::type + inline typename result_of::invoke_function_object::type operator()(Seq & s) const { return fusion::invoke_function_object< @@ -60,7 +61,7 @@ namespace boost { namespace fusion } template - inline typename result_of::invoke_function_object::type + inline typename result_of::invoke_function_object::type operator()(Seq & s) { return fusion::invoke_function_object< @@ -68,11 +69,17 @@ namespace boost { namespace fusion } template - struct result; + struct result + { }; - template - struct result - : result_of::invoke_function_object + template + struct result< Self const (Seq) > + : result_of::invoke_function_object + { }; + + template + struct result< Self(Seq) > + : result_of::invoke_function_object { }; }; diff --git a/include/boost/fusion/functional/adapter/fused_procedure.hpp b/include/boost/fusion/functional/adapter/fused_procedure.hpp index 43c94759..7dfded18 100644 --- a/include/boost/fusion/functional/adapter/fused_procedure.hpp +++ b/include/boost/fusion/functional/adapter/fused_procedure.hpp @@ -35,43 +35,42 @@ namespace boost { namespace fusion { } template - inline typename result_of::invoke_procedure::type - operator()(Seq const & s) const + inline void operator()(Seq const & s) const { - return fusion::invoke_procedure< - func_const_fwd_t >(this->fnc_transformed,s); + fusion::invoke_procedure< + func_const_fwd_t >(this->fnc_transformed,s); } template - inline typename result_of::invoke_procedure::type - operator()(Seq const & s) + inline void operator()(Seq const & s) { - return fusion::invoke_procedure< - func_fwd_t >(this->fnc_transformed,s); + fusion::invoke_procedure< + func_fwd_t >(this->fnc_transformed,s); } template - inline typename result_of::invoke_procedure::type - operator()(Seq & s) const + inline void operator()(Seq & s) const { - return fusion::invoke_procedure< - func_const_fwd_t >(this->fnc_transformed,s); + fusion::invoke_procedure< + func_const_fwd_t >(this->fnc_transformed,s); } template - inline typename result_of::invoke_procedure::type - operator()(Seq & s) + inline void operator()(Seq & s) { - return fusion::invoke_procedure< - func_fwd_t >(this->fnc_transformed,s); + return fusion::invoke_procedure< + func_fwd_t >(this->fnc_transformed,s); } - template + template struct result - : result_of::invoke_procedure { }; - typedef void result_type; + template + struct result< Self(Seq) > + { + typedef void type; + }; }; }} diff --git a/include/boost/fusion/functional/adapter/limits.hpp b/include/boost/fusion/functional/adapter/limits.hpp index fa2e5a3b..476fe021 100644 --- a/include/boost/fusion/functional/adapter/limits.hpp +++ b/include/boost/fusion/functional/adapter/limits.hpp @@ -31,6 +31,9 @@ # elif BOOST_FUSION_UNFUSED_TYPED_MAX_ARITY > FUSION_MAX_VECTOR_SIZE # error "BOOST_FUSION_UNFUSED_TYPED_MAX_ARITY > FUSION_MAX_VECTOR_SIZE" # endif +# if !defined(BOOST_FUSION_CONSTRUCTOR_MAX_ARITY) +# define BOOST_FUSION_CONSTRUCTOR_MAX_ARITY 6 +# endif #endif diff --git a/include/boost/fusion/functional/adapter/unfused_generic.hpp b/include/boost/fusion/functional/adapter/unfused_generic.hpp index 00c60c2c..eae10f12 100644 --- a/include/boost/fusion/functional/adapter/unfused_generic.hpp +++ b/include/boost/fusion/functional/adapter/unfused_generic.hpp @@ -56,17 +56,23 @@ namespace boost { namespace fusion using base::operator(); - template - struct result; + template + struct result + { }; - template - struct result()> - : base::r0 + template + struct result< Self const () > + : base::call_const_0_result_class + { }; + + template + struct result< Self() > + : base::call_0_result_class { }; #define BOOST_FUSION_CODE(tpl_params,arg_types,params,args) \ template \ - inline typename function::template result)>::type \ operator()(params) const \ { \ @@ -91,16 +97,22 @@ namespace boost { namespace fusion #define N BOOST_PP_ITERATION_1 #include BOOST_PP_ITERATE() #undef N + #undef BOOST_FUSION_CODE }; }} -namespace boost { - template - struct result_of()> +namespace boost +{ + template + struct result_of const ()> { - typedef boost::fusion::unfused_generic function; - typedef typename function::template result::type type; + typedef typename boost::fusion::unfused_generic::call_const_0_result type; + }; + template + struct result_of()> + { + typedef typename boost::fusion::unfused_generic::call_0_result type; }; } @@ -115,9 +127,17 @@ namespace boost { #include #if BOOST_PP_SLOT_1() == 0 - template + template struct result - (BOOST_PP_ENUM_PARAMS(N,T))> + < Self const (BOOST_PP_ENUM_PARAMS(N,T)) > + : function::template result::type BOOST_PP_INTERCEPT) >)> + { }; + + template + struct result + < Self(BOOST_PP_ENUM_PARAMS(N,T)) > : function::template result::type BOOST_PP_INTERCEPT) >)> @@ -126,7 +146,7 @@ namespace boost { #if BOOST_WORKAROUND(BOOST_MSVC,BOOST_TESTED_AT(1400)) template - inline typename function::template result)>::type operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,PT,a)) const { diff --git a/include/boost/fusion/functional/adapter/unfused_lvalue_args.hpp b/include/boost/fusion/functional/adapter/unfused_lvalue_args.hpp index 25f547de..cd8e0508 100644 --- a/include/boost/fusion/functional/adapter/unfused_lvalue_args.hpp +++ b/include/boost/fusion/functional/adapter/unfused_lvalue_args.hpp @@ -55,12 +55,18 @@ namespace boost { namespace fusion using base::operator(); - template - struct result; + template + struct result + { }; - template - struct result()> - : base::r0 + template + struct result< Self const () > + : base::call_const_0_result_class + { }; + + template + struct result< Self() > + : base::call_0_result_class { }; #define BOOST_PP_FILENAME_1 \ @@ -71,12 +77,17 @@ namespace boost { namespace fusion }; }} -namespace boost { - template - struct result_of()> +namespace boost +{ + template + struct result_of< boost::fusion::unfused_lvalue_args const () > { - typedef boost::fusion::unfused_lvalue_args function; - typedef typename function::template result::type type; + typedef typename boost::fusion::unfused_lvalue_args::call_const_0_result type; + }; + template + struct result_of< boost::fusion::unfused_lvalue_args() > + { + typedef typename boost::fusion::unfused_lvalue_args::call_0_result type; }; } @@ -89,12 +100,18 @@ namespace boost { //////////////////////////////////////////////////////////////////////////////// #define N BOOST_PP_ITERATION() - template - struct result - - : function::template result< function(BOOST_PP_CAT(fusion::vector,N)< - BOOST_PP_ENUM_BINARY_PARAMS(N,typename detail::mref::type - BOOST_PP_INTERCEPT) >)> + template + struct result< Self const (BOOST_PP_ENUM_PARAMS(N,T)) > + : function::template result< function const ( + BOOST_PP_CAT(fusion::vector,N)< BOOST_PP_ENUM_BINARY_PARAMS(N, + typename detail::mref::type BOOST_PP_INTERCEPT) >)> + { }; + + template + struct result< Self(BOOST_PP_ENUM_PARAMS(N,T)) > + : function::template result< function ( + BOOST_PP_CAT(fusion::vector,N)< BOOST_PP_ENUM_BINARY_PARAMS(N, + typename detail::mref::type BOOST_PP_INTERCEPT) >)> { }; template diff --git a/include/boost/fusion/functional/adapter/unfused_rvalue_args.hpp b/include/boost/fusion/functional/adapter/unfused_rvalue_args.hpp index 62b34463..9fbbabfc 100644 --- a/include/boost/fusion/functional/adapter/unfused_rvalue_args.hpp +++ b/include/boost/fusion/functional/adapter/unfused_rvalue_args.hpp @@ -55,12 +55,18 @@ namespace boost { namespace fusion using base::operator(); - template - struct result; + template + struct result + { }; - template - struct result()> - : base::r0 + template + struct result< Self const () > + : base::call_const_0_result_class + { }; + + template + struct result< Self() > + : base::call_0_result_class { }; #define BOOST_PP_FILENAME_1 \ @@ -71,12 +77,17 @@ namespace boost { namespace fusion }; }} -namespace boost { - template - struct result_of()> +namespace boost +{ + template + struct result_of const ()> { - typedef boost::fusion::unfused_rvalue_args function; - typedef typename function::template result::type type; + typedef typename boost::fusion::unfused_rvalue_args::call_const_0_result type; + }; + template + struct result_of()> + { + typedef typename boost::fusion::unfused_rvalue_args::call_0_result type; }; } @@ -89,11 +100,18 @@ namespace boost { //////////////////////////////////////////////////////////////////////////////// #define N BOOST_PP_ITERATION() - template - struct result - : function::template result::type - BOOST_PP_INTERCEPT) >)> + template + struct result< Self const (BOOST_PP_ENUM_PARAMS(N,T)) > + : function::template result< function const ( + BOOST_PP_CAT(fusion::vector,N)< BOOST_PP_ENUM_BINARY_PARAMS(N, + typename detail::cref::type BOOST_PP_INTERCEPT) >)> + { }; + + template + struct result< Self (BOOST_PP_ENUM_PARAMS(N,T)) > + : function::template result< function ( + BOOST_PP_CAT(fusion::vector,N)< BOOST_PP_ENUM_BINARY_PARAMS(N, + typename detail::cref::type BOOST_PP_INTERCEPT) >)> { }; template diff --git a/include/boost/fusion/functional/adapter/unfused_typed.hpp b/include/boost/fusion/functional/adapter/unfused_typed.hpp index 6f85b929..54a2049a 100644 --- a/include/boost/fusion/functional/adapter/unfused_typed.hpp +++ b/include/boost/fusion/functional/adapter/unfused_typed.hpp @@ -104,12 +104,18 @@ namespace boost { namespace fusion : fnc_transformed(f) { } - template - struct result; + template + struct result + { }; - template - struct result()> - : base::r0 + template + struct result< Self const () > + : base::call_const_0_result_class + { }; + + template + struct result< Self() > + : base::call_0_result_class { }; }; @@ -119,15 +125,21 @@ namespace boost { namespace fusion }} -namespace boost { - template - struct result_of()> +namespace boost +{ + template + struct result_of< boost::fusion::unfused_typed const () > { - typedef boost::fusion::unfused_typed function; - typedef typename function::template result::type type; + typedef typename boost::fusion::unfused_typed::call_const_0_result type; + }; + template + struct result_of< boost::fusion::unfused_typed() > + { + typedef typename boost::fusion::unfused_typed::call_0_result type; }; } + #define BOOST_FUSION_FUNCTIONAL_ADAPTER_UNFUSED_TYPED_HPP_INCLUDED #else // defined(BOOST_PP_IS_ITERATING) /////////////////////////////////////////////////////////////////////////////// @@ -149,26 +161,21 @@ namespace boost { Derived,Function,Sequence>::type base; typedef typename remove_const::type>::type function; - - // Notes: - // - conversion to fusion::vector might not be perfect (there is - // currently no "inrinsic converting ctor" that would allow us - // to let the user choose the sequence implementation) - // - value_at_c (instead of iteration) is OK because of conversion - // to fusion::vector - we would need iteration for arbitrary - // sequences typedef typename result_of::as_vector::type arg_vector_t; + + protected: + typedef typename function:: + template result BOOST_PP_CAT(rc,N); + typedef typename function:: + template result BOOST_PP_CAT(r,N); public: using base::operator(); - typedef typename function:: - template result BOOST_PP_CAT(r,N); - #define M(z,i,s) \ typename call_param::type>::type a##i - inline typename function::template result::type + inline typename function::template result::type operator()(BOOST_PP_ENUM(N,M,arg_vector_t)) const { arg_vector_t arg(BOOST_PP_ENUM_PARAMS(N,a)); @@ -190,11 +197,20 @@ namespace boost { } // namespace detail template - template - struct unfused_typed::result - + template + struct unfused_typed::result< + Self const (BOOST_PP_ENUM_PARAMS(N,T)) > + : BOOST_PP_CAT(base::rc,N) + { }; + +#if !BOOST_WORKAROUND(BOOST_MSVC, < 1400) + template + template + struct unfused_typed::result< + Self (BOOST_PP_ENUM_PARAMS(N,T)) > : BOOST_PP_CAT(base::r,N) { }; +#endif #undef N #endif // defined(BOOST_PP_IS_ITERATING) diff --git a/test/functional/make_unfused_generic.cpp b/test/functional/make_unfused_generic.cpp index 7536f790..491fc93b 100644 --- a/test/functional/make_unfused_generic.cpp +++ b/test/functional/make_unfused_generic.cpp @@ -38,11 +38,11 @@ template struct test_func : Base { - template + template struct result; - template - struct result(Seq)> + template + struct result< Self(Seq) > : mpl::if_< mpl::and_< fusion::result_of::empty, RemoveNullary >, boost::blank, mpl::identity >::type { }; diff --git a/test/functional/make_unfused_lvalue_args.cpp b/test/functional/make_unfused_lvalue_args.cpp index 7a185740..20dae6ed 100644 --- a/test/functional/make_unfused_lvalue_args.cpp +++ b/test/functional/make_unfused_lvalue_args.cpp @@ -37,11 +37,11 @@ template struct test_func : Base { - template + template struct result; - template - struct result(Seq)> + template + struct result< Self(Seq) > : mpl::if_< mpl::and_< fusion::result_of::empty, RemoveNullary >, boost::blank, mpl::identity >::type { }; diff --git a/test/functional/make_unfused_rvalue_args.cpp b/test/functional/make_unfused_rvalue_args.cpp index 579d15ea..8746a6af 100644 --- a/test/functional/make_unfused_rvalue_args.cpp +++ b/test/functional/make_unfused_rvalue_args.cpp @@ -35,11 +35,11 @@ template struct test_func : Base { - template + template struct result; - template - struct result(Seq)> + template + struct result< Self(Seq) > : mpl::if_< mpl::and_< fusion::result_of::empty, RemoveNullary >, boost::blank, mpl::identity >::type { }; diff --git a/test/functional/unfused_generic.cpp b/test/functional/unfused_generic.cpp index af4c7134..3810bdcb 100644 --- a/test/functional/unfused_generic.cpp +++ b/test/functional/unfused_generic.cpp @@ -35,14 +35,14 @@ template struct test_func : Base { - template + template struct result; - template - struct result(Seq)> + template + struct result< Self(Seq) > : mpl::if_< mpl::and_< fusion::result_of::empty, RemoveNullary >, boost::blank, mpl::identity >::type - {}; + { }; template long operator()(Seq const & seq) const @@ -51,7 +51,7 @@ struct test_func return fusion::fold(seq, state, fold_op()); } - template < typename Seq > + template long operator()(Seq const & seq) { long state = 100; @@ -89,7 +89,7 @@ void result_type_tests() BOOST_TEST(( has_type< test_func_0::result >::value )); BOOST_TEST(( has_type< test_func_1::result >::value )); - BOOST_TEST(( ! has_type< test_func_1::result >::value )); + BOOST_TEST(( ! has_type< test_func_1::result >::value )); BOOST_TEST(( is_same< boost::result_of< test_func_0() >::type, long >::value )); BOOST_TEST(( is_same< boost::result_of< test_func_1(int) >::type, long >::value )); } @@ -112,8 +112,12 @@ int main() BOOST_TEST(unfused_func_c_ref() == 0); long lvalue = 12; + // also test const lvalues to pick up compiler deficiencies in that area + int const clvalue_1 = 1; + long const clvalue_2 = 2; + static const long expected = 1*sizeof(int) + 2*sizeof(long) + 7*sizeof(char); - BOOST_TEST(unfused_func(lvalue,lvalue,1,2l,'\007') == 100 + expected); + BOOST_TEST(unfused_func(lvalue,lvalue,clvalue_1,clvalue_2,'\007') == 100 + expected); BOOST_TEST(lvalue == 12 + 2*sizeof(long)); BOOST_TEST(unfused_func_ref(lvalue,lvalue,1,2l,'\007') == 100 + expected); BOOST_TEST(lvalue == 12 + 4*sizeof(long)); diff --git a/test/functional/unfused_lvalue_args.cpp b/test/functional/unfused_lvalue_args.cpp index 3919e527..26b4535d 100644 --- a/test/functional/unfused_lvalue_args.cpp +++ b/test/functional/unfused_lvalue_args.cpp @@ -32,11 +32,11 @@ template struct test_func : Base { - template + template struct result; - template - struct result(Seq)> + template + struct result< Self(Seq) > : mpl::if_< mpl::and_< fusion::result_of::empty, RemoveNullary >, boost::blank, mpl::identity >::type { }; @@ -48,7 +48,7 @@ struct test_func return fusion::fold(seq, state, fold_op()); } - template < typename Seq > + template long operator()(Seq const & seq) { long state = 100; diff --git a/test/functional/unfused_rvalue_args.cpp b/test/functional/unfused_rvalue_args.cpp index b15f2f95..da694f07 100644 --- a/test/functional/unfused_rvalue_args.cpp +++ b/test/functional/unfused_rvalue_args.cpp @@ -32,11 +32,11 @@ template struct test_func : Base { - template + template struct result; - template - struct result(Seq)> + template + struct result< Self(Seq) > : mpl::if_< mpl::and_< fusion::result_of::empty, RemoveNullary >, boost::blank, mpl::identity >::type { }; diff --git a/test/functional/unfused_typed.cpp b/test/functional/unfused_typed.cpp index 9e81444d..5b119ba3 100644 --- a/test/functional/unfused_typed.cpp +++ b/test/functional/unfused_typed.cpp @@ -45,8 +45,8 @@ struct test_func template struct result; - template - struct result(Seq)> + template + struct result : mpl::if_< typename mpl::apply::type, mpl::identity, boost::blank >::type { };