diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 17fd4d5..5192172 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -38,10 +38,25 @@ struct tr1_result_of #endif #ifdef BOOST_RESULT_OF_USE_DECLTYPE - -// Uses declval following N3225 20.7.7.6 when F is not a pointer. template -struct result_of +struct result_of + : detail::cpp0x_result_of { }; +#endif // BOOST_RESULT_OF_USE_DECLTYPE + +#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK +template +struct result_of + : mpl::if_, detail::has_result >, + tr1_result_of, + detail::cpp0x_result_of >::type { }; +#endif // BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK + +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) + +namespace detail { + +template +struct cpp0x_result_of : mpl::if_< is_member_function_pointer , detail::tr1_result_of_impl< @@ -54,8 +69,6 @@ struct result_of >::type {}; -namespace detail { - #ifdef BOOST_NO_SFINAE_EXPR template @@ -139,7 +152,7 @@ struct cpp0x_result_of_impl diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp index 97e9618..a530c3a 100644 --- a/include/boost/utility/result_of.hpp +++ b/include/boost/utility/result_of.hpp @@ -38,18 +38,27 @@ // Use the decltype-based version of result_of by default if the compiler // supports N3276 . -// The user can force the choice by defining either BOOST_RESULT_OF_USE_DECLTYPE or -// BOOST_RESULT_OF_USE_TR1, but not both! -#if defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1) -# error Both BOOST_RESULT_OF_USE_DECLTYPE and BOOST_RESULT_OF_USE_TR1 cannot be defined at the same time. +// The user can force the choice by defining BOOST_RESULT_OF_USE_DECLTYPE, +// BOOST_RESULT_OF_USE_TR1, or BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK but not more than one! +#if (defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1)) || \ + (defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)) || \ + (defined(BOOST_RESULT_OF_USE_TR1) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)) +# error More than one of BOOST_RESULT_OF_USE_DECLTYPE, BOOST_RESULT_OF_USE_TR1 and \ + BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK cannot be defined at the same time. +#endif + +#if defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) && defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE) +# error Cannot fallback to decltype if BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE is not defined. #endif #ifndef BOOST_RESULT_OF_USE_TR1 # ifndef BOOST_RESULT_OF_USE_DECLTYPE -# ifndef BOOST_NO_CXX11_DECLTYPE_N3276 // this implies !defined(BOOST_NO_CXX11_DECLTYPE) -# define BOOST_RESULT_OF_USE_DECLTYPE -# else -# define BOOST_RESULT_OF_USE_TR1 +# ifndef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK +# ifndef BOOST_NO_CXX11_DECLTYPE_N3276 // this implies !defined(BOOST_NO_CXX11_DECLTYPE) +# define BOOST_RESULT_OF_USE_DECLTYPE +# else +# define BOOST_RESULT_OF_USE_TR1 +# endif # endif # endif #endif @@ -64,8 +73,12 @@ namespace detail { BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type) +BOOST_MPL_HAS_XXX_TEMPLATE_DEF(result) + template struct tr1_result_of_impl; +template struct cpp0x_result_of; + #ifdef BOOST_NO_SFINAE_EXPR // There doesn't seem to be any other way to turn this off such that the presence of diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp index d06ec64..6c60f99 100644 --- a/test/result_of_test.cpp +++ b/test/result_of_test.cpp @@ -5,6 +5,12 @@ // 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) +// Examples: +// To run the default test: +// $ cd libs/utility/test && bjam +// To test decltype on g++ 2.7: +// $ cd libs/utility/test && bjam cxxflags="-std=c++11 -D BOOST_RESULT_OF_USE_DECLTYPE" + #include // For more information, see http://www.boost.org/libs/utility @@ -190,7 +196,7 @@ int main() BOOST_STATIC_ASSERT((is_same(void)>::type, void>::value)); // Prior to decltype, result_of could not deduce the return type - // nullary function objects unless they exposed a result_type. + // of nullary function objects unless they exposed a result_type. #if defined(BOOST_RESULT_OF_USE_DECLTYPE) BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); @@ -273,7 +279,7 @@ int main() BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type,int>::value)); -#if defined(BOOST_RESULT_OF_USE_DECLTYPE) +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) BOOST_STATIC_ASSERT((is_same::type, short>::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); @@ -301,7 +307,7 @@ int main() #endif #endif -#if defined(BOOST_RESULT_OF_USE_DECLTYPE) +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) int i = 123; sfinae_test(sfinae_test_f, i); #endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) diff --git a/utility.htm b/utility.htm index 974776e..1101cc6 100644 --- a/utility.htm +++ b/utility.htm @@ -259,6 +259,46 @@ typedef boost::result_of< represent the return type of operator() given a call expression.

+

Additionally, boost::result_of + provides a third mode of operation, which some users + may find convenient. When + BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK + is defined, boost::result_of behaves as + follows. If the function object has a member + type result_type or member + template result<>, then + boost::result_of will use the TR1 + protocol. Otherwise, + boost::result_of will + use decltype. Using TR1 with + a declytpe fallback may workaround + certain problems at the cost of portability. For + example: +

    +
  • Deficient compiler: If your code + requires boost::result_of to work + with incomplete return types but your + compiler's decltype implementation + does not support incomplete return types, then you + can use the TR1 protocol as a workaround. Support + for incomplete return types was added late in the + C++11 standardization process + (see N3276) + and is not implemented by some compilers.
  • + +
  • Deficient legacy code: If your existing TR1 + function object advertises a different type than + the actual result type deduced + by decltype, then using TR1 with a + decltype fallback will allow you to + work with both your existing TR1 function objects + and new C++11 function object. This situation + could occur if your legacy function objects + misused the TR1 protocol. See the documentation on + known differences + between boost::result_of and TR1.
  • +
+

This implementation of result_of requires class template partial specialization, the