Index: boost/utility/detail/result_of_iterate.hpp =================================================================== --- boost/utility/detail/result_of_iterate.hpp (revision 81545) +++ boost/utility/detail/result_of_iterate.hpp (working copy) @@ -37,11 +37,11 @@ (boost::detail::has_result_type::value)> >::type { }; #endif -#ifdef BOOST_RESULT_OF_USE_DECLTYPE +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) // Uses declval following N3225 20.7.7.6 when F is not a pointer. template -struct result_of +struct cpp0x_result_of : mpl::if_< is_member_function_pointer , detail::tr1_result_of_impl< @@ -139,8 +139,23 @@ } // namespace detail -#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) +#if defined(BOOST_RESULT_OF_USE_DECLTYPE) +template +struct result_of + : cpp0x_result_of { }; +#endif + +#if defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) +template +struct result_of + : mpl::if_, detail::has_result >, + tr1_result_of, + cpp0x_result_of >::type { }; +#endif + +#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) + #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) template struct result_of Index: boost/utility/result_of.hpp =================================================================== --- boost/utility/result_of.hpp (revision 81545) +++ boost/utility/result_of.hpp (working copy) @@ -38,18 +38,31 @@ // 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 the presence of a nested result struct cannot be tested. +#endif + #ifndef BOOST_RESULT_OF_USE_TR1 # ifndef BOOST_RESULT_OF_USE_DECLTYPE -# ifndef BOOST_NO_DECLTYPE_N3276 // this implies !defined(BOOST_NO_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_DECLTYPE_N3276 // this implies !defined(BOOST_NO_DECLTYPE) +# define BOOST_RESULT_OF_USE_DECLTYPE +# else +# if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE) +# define BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK +# else +# define BOOST_RESULT_OF_USE_TR1 +# endif +# endif # endif # endif #endif @@ -58,12 +71,15 @@ template struct result_of; template struct tr1_result_of; // a TR1-style implementation of result_of +template struct cpp0x_result_of; #if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) namespace detail { BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type) +BOOST_MPL_HAS_XXX_TEMPLATE_DEF(result) + template struct tr1_result_of_impl; #ifdef BOOST_NO_SFINAE_EXPR Index: libs/utility/test/result_of_test.cpp =================================================================== --- libs/utility/test/result_of_test.cpp (revision 81545) +++ libs/utility/test/result_of_test.cpp (working copy) @@ -150,6 +150,21 @@ return i; } +#if !defined(BOOST_NO_CXX11_LAMBDAS) && !defined(BOOST_RESULT_OF_USE_TR1) +template +void check_void_result_of_lambda_is(F f) +{ + BOOST_STATIC_ASSERT((boost::is_same::type, R>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, R>::value)); +} +template +void check_unary_result_of_lambda_is(F f) +{ + BOOST_STATIC_ASSERT((boost::is_same::type, R>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, R>::value)); +} +#endif + struct X {}; int main() @@ -169,6 +184,7 @@ typedef int (X::*mem_func_ptr_v)(float) volatile; typedef int (X::*mem_func_ptr_cv)(float) const volatile; typedef int (X::*mem_func_ptr_0)(); + typedef int (*pf_t)(int); BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same::type, int>::value)); @@ -215,6 +231,36 @@ BOOST_STATIC_ASSERT((is_same(char)>::type, int>::value)); #endif +#if !defined(BOOST_NO_CXX11_DECLTYPE) + BOOST_STATIC_ASSERT((is_same::type, char>::value)); + BOOST_STATIC_ASSERT((is_same(char)>::type, char>::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)); + 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)); + 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,int>::value)); + + BOOST_STATIC_ASSERT((is_same::type, double>::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value)); + BOOST_STATIC_ASSERT((is_same::type, int &>::value)); + BOOST_STATIC_ASSERT((is_same::type, int const &>::value)); + BOOST_STATIC_ASSERT((is_same::type, int volatile &>::value)); + BOOST_STATIC_ASSERT((is_same::type, int const volatile &>::value)); +#endif + BOOST_STATIC_ASSERT((is_same::type, int>::value)); BOOST_STATIC_ASSERT((is_same(char)>::type, int>::value)); @@ -266,14 +312,13 @@ BOOST_STATIC_ASSERT((is_same::type, int volatile &>::value)); BOOST_STATIC_ASSERT((is_same::type, int const volatile &>::value)); - typedef int (*pf_t)(int); 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,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)); @@ -306,5 +351,15 @@ sfinae_test(sfinae_test_f, i); #endif // defined(BOOST_RESULT_OF_USE_DECLTYPE) +#if !defined(BOOST_NO_CXX11_LAMBDAS) && !defined(BOOST_RESULT_OF_USE_TR1) + check_void_result_of_lambda_is([]{ return 0.f; }); + check_void_result_of_lambda_is([]() -> double { return 0; }); + check_void_result_of_lambda_is([]{}); + + check_unary_result_of_lambda_is([](int){ return 0.f; }); + check_unary_result_of_lambda_is([](int) -> double { return 0; }); + check_unary_result_of_lambda_is([](int){}); +#endif + return 0; } Index: libs/utility/utility.htm =================================================================== --- libs/utility/utility.htm (revision 81545) +++ libs/utility/utility.htm (working copy) @@ -185,15 +185,15 @@ >::type type; // type is int -

You can test whether result_of is using - decltype by checking if the macro +

You can test whether result_of is automatically + using decltype by checking if the macro BOOST_RESULT_OF_USE_DECLTYPE is defined after including result_of.hpp. You can also force result_of to use decltype by defining BOOST_RESULT_OF_USE_DECLTYPE prior to including result_of.hpp.

-

If decltype is not used, +

If decltype is not supported by the compiler, then automatic result type deduction of function objects is not possible. Instead, result_of uses the following protocol to allow the programmer to @@ -255,6 +255,28 @@ represent the return type of operator() given a call expression.

+

If your compiler supports decltype in a form + which is inadequate to justify its automatic use (see the + proposal which the compiler must implement to be considered adequate), + a hybrid approach is used. If a member type + result_type or a member template struct + result is present, then the + non-decltype result_of protocol is + used. If neither type is present, then result_of + falls back on the decltype-based protocol. This + allows result_of to be used on compilers which + support C++11 lambda functions (which define neither + result_type nor result) and partially support + decltype. You can test whether + result_of is automatically using this hybrid + approach by checking if the macro + BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK + is defined after including result_of.hpp. You + can also force result_of to use this hybrid + approach by defining + BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK + prior to including result_of.hpp.

+

This implementation of result_of requires class template partial specialization, the