From 0f43c44e978041214cc3e6bf20ec427309063f7c Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Wed, 26 Sep 2012 18:52:08 +0000 Subject: [PATCH] result_of: merge [80636],[80654],[80655],[80656],[80712] from trunk [SVN r80713] --- .../utility/detail/result_of_iterate.hpp | 127 +++++++++--------- include/boost/utility/result_of.hpp | 73 ++++++++-- test/result_of_test.cpp | 12 ++ 3 files changed, 137 insertions(+), 75 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 4d35fc0..17fd4d5 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -23,31 +23,29 @@ #endif #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) -template +template struct tr1_result_of : mpl::if_< mpl::or_< is_pointer, is_member_function_pointer > , boost::detail::tr1_result_of_impl< - typename remove_cv::type, - typename remove_cv::type(BOOST_RESULT_OF_ARGS), + typename remove_cv::type, + typename remove_cv::type(BOOST_RESULT_OF_ARGS), (boost::detail::has_result_type::value)> , boost::detail::tr1_result_of_impl< F, - F(BOOST_RESULT_OF_ARGS), + F(BOOST_RESULT_OF_ARGS), (boost::detail::has_result_type::value)> >::type { }; #endif #ifdef BOOST_RESULT_OF_USE_DECLTYPE // Uses declval following N3225 20.7.7.6 when F is not a pointer. -template +template struct result_of : mpl::if_< is_member_function_pointer , detail::tr1_result_of_impl< - typename remove_cv::type, + typename remove_cv::type, typename remove_cv::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false > , detail::cpp0x_result_of_impl< @@ -58,51 +56,60 @@ struct result_of namespace detail { -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) +#ifdef BOOST_NO_SFINAE_EXPR -template -class is_callable { - typedef char (&pass)[1]; - typedef char (&fail)[2]; +template +struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION()); - template - struct sub {}; - template - struct stub {}; - - template - static pass test(sub - , stub< - decltype( - boost::declval()( - BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) - ) - ) - >* x = 0); - static fail test(...); - -public: - const static bool value = sizeof(pass) == sizeof(test(sub())); - typedef typename boost::mpl::bool_::type type; +template +struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION()) { + R operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T)) const; + typedef result_of_private_type const &(*pfn_t)(...); + operator pfn_t() const volatile; }; -template +template +struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION()); + +template +struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION()) + : BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION()) +{}; + +template +struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION()) + : BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION()) +{}; + +template +struct BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION()) + : mpl::eval_if< + is_class::type>, + result_of_wrap_callable_class, + mpl::identity::type> > + > +{}; + +template +struct BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) { + typedef typename BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())::type wrapper_t; + static const bool value = ( + sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type( + (boost::declval()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT)), result_of_weird_type()) + )) + ); + typedef mpl::bool_ type; +}; + +template struct cpp0x_result_of_impl : lazy_enable_if< - is_callable + BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) , cpp0x_result_of_impl > {}; -template +template struct cpp0x_result_of_impl { typedef decltype( @@ -112,11 +119,10 @@ struct cpp0x_result_of_impl -struct cpp0x_result_of_impl +struct cpp0x_result_of_impl()( BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) @@ -129,15 +135,14 @@ struct cpp0x_result_of_impl +template struct result_of : tr1_result_of { }; #endif @@ -146,27 +151,24 @@ struct result_of #undef BOOST_RESULT_OF_ARGS -#if BOOST_PP_ITERATION() >= 1 +#if BOOST_PP_ITERATION() >= 1 namespace detail { -template +template struct tr1_result_of_impl { typedef R type; }; -template +template struct tr1_result_of_impl { typedef R type; }; #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) -template +template struct tr1_result_of_impl @@ -174,8 +176,7 @@ struct tr1_result_of_impl +template struct tr1_result_of_impl +template struct tr1_result_of_impl +template struct tr1_result_of_impl -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include #include #include +#include #include +#include #include +#include #include #include #include +#include #include #include @@ -61,21 +66,67 @@ BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type) template struct tr1_result_of_impl; -#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) +#ifdef BOOST_NO_SFINAE_EXPR + +struct result_of_private_type {}; + +struct result_of_weird_type { + template + friend result_of_weird_type operator,(T const &, result_of_weird_type); + friend result_of_private_type operator,(result_of_private_type, result_of_weird_type); +}; + +typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1 +typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2 + +result_of_no_type result_of_is_private_type(result_of_weird_type); +result_of_yes_type result_of_is_private_type(result_of_private_type); + +template +struct result_of_callable_class : C { + result_of_callable_class(); + typedef result_of_private_type const &(*pfn_t)(...); + operator pfn_t() const volatile; +}; + +template +struct result_of_wrap_callable_class { + typedef result_of_callable_class type; +}; + +template +struct result_of_wrap_callable_class { + typedef result_of_callable_class const type; +}; + +template +struct result_of_wrap_callable_class { + typedef result_of_callable_class volatile type; +}; + +template +struct result_of_wrap_callable_class { + typedef result_of_callable_class const volatile type; +}; + +template +struct result_of_wrap_callable_class { + typedef typename result_of_wrap_callable_class::type &type; +}; -template class is_callable; template struct cpp0x_result_of_impl; -#else // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) +#else // BOOST_NO_SFINAE_EXPR template struct result_of_always_void { - typedef void type; + typedef void type; }; + template struct cpp0x_result_of_impl {}; -#endif // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) +#endif // BOOST_NO_SFINAE_EXPR template struct result_of_void_impl diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp index 0c2834f..61592f5 100644 --- a/test/result_of_test.cpp +++ b/test/result_of_test.cpp @@ -160,6 +160,10 @@ int main() typedef int (&func_ref)(float, double); typedef int (*func_ptr_0)(); typedef int (&func_ref_0)(); + typedef void (*func_ptr_void)(float, double); + typedef void (&func_ref_void)(float, double); + typedef void (*func_ptr_void_0)(); + typedef void (&func_ref_void_0)(); typedef int (X::*mem_func_ptr)(float); typedef int (X::*mem_func_ptr_c)(float) const; typedef int (X::*mem_func_ptr_v)(float) volatile; @@ -218,6 +222,10 @@ int main() BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); @@ -228,6 +236,10 @@ int main() BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); + BOOST_STATIC_ASSERT((is_same::type, void>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value));