From ac9f617f7f629270180d8a2d75ce9da603b0161c Mon Sep 17 00:00:00 2001 From: Daniel Walker Date: Wed, 19 Sep 2012 23:10:08 +0000 Subject: [PATCH] SFINAE enabled result_of fixes [7343] [SVN r80605] --- .../utility/detail/result_of_iterate.hpp | 66 ++++++++++++++++++- include/boost/utility/result_of.hpp | 18 ++++- test/result_of_test.cpp | 26 ++++++++ 3 files changed, 107 insertions(+), 3 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 5cf30b6..df05bbf 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -58,17 +58,79 @@ struct result_of namespace detail { +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) + template -struct cpp0x_result_of_impl +class is_callable { + typedef char (&pass)[1]; + typedef char (&fail)[2]; + + 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 cpp0x_result_of_impl + : lazy_enable_if< + is_callable + , cpp0x_result_of_impl + > +{}; + +template +struct cpp0x_result_of_impl { typedef decltype( boost::declval()( - BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), declval() BOOST_PP_INTERCEPT) + BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) ) ) type; }; +#else // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) + +template +struct cpp0x_result_of_impl()( + BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) + ) + )>::type> { + typedef decltype( + boost::declval()( + BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval() BOOST_PP_INTERCEPT) + ) + ) type; +}; + +#endif // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) + } // namespace detail #else // defined(BOOST_RESULT_OF_USE_DECLTYPE) diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp index 93b7264..222c9c9 100644 --- a/include/boost/utility/result_of.hpp +++ b/include/boost/utility/result_of.hpp @@ -25,6 +25,7 @@ #include #include #include +#include #ifndef BOOST_RESULT_OF_NUM_ARGS # define BOOST_RESULT_OF_NUM_ARGS 16 @@ -59,7 +60,22 @@ namespace detail { BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type) template struct tr1_result_of_impl; -template struct cpp0x_result_of_impl; + +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) + +template class is_callable; +template struct cpp0x_result_of_impl; + +#else // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) + +template +struct result_of_always_void +{ + typedef void type; +}; +template struct cpp0x_result_of_impl {}; + +#endif // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700)) template struct result_of_void_impl diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp index 3f6da9e..0c2834f 100644 --- a/test/result_of_test.cpp +++ b/test/result_of_test.cpp @@ -129,6 +129,27 @@ struct no_result_type_or_result_template #endif }; +// sfinae_tests are derived from example code from Joel de Guzman, +// which demonstrated the interaction between result_of and SFINAE. +template +typename boost::result_of::type +sfinae_test(F f, Arg const& arg) +{ + return f(arg); +} + +template +typename boost::result_of::type +sfinae_test(F f, Arg& arg) +{ + return f(arg); +} + +int sfinae_test_f(int& i) +{ + return i; +} + struct X {}; int main() @@ -268,5 +289,10 @@ int main() #endif #endif +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) + int i = 123; + sfinae_test(sfinae_test_f, i); +#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) + return 0; }