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