Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r84949 - in trunk: boost/utility boost/utility/detail libs/utility libs/utility/test
From: daniel.j.walker_at_[hidden]
Date: 2013-07-03 18:14:27


Author: djwalker
Date: 2013-07-03 18:14:27 EDT (Wed, 03 Jul 2013)
New Revision: 84949
URL: http://svn.boost.org/trac/boost/changeset/84949

Log:
added new result_of mode that uses TR1 with a decltype fallback as suggested by Nathan Crookston; fixes #7753

Text files modified:
   trunk/boost/utility/detail/result_of_iterate.hpp | 23 ++++++++++++++++++-----
   trunk/boost/utility/result_of.hpp | 29 +++++++++++++++++++++--------
   trunk/libs/utility/test/result_of_test.cpp | 12 +++++++++---
   trunk/libs/utility/utility.htm | 40 ++++++++++++++++++++++++++++++++++++++++
   4 files changed, 88 insertions(+), 16 deletions(-)

Modified: trunk/boost/utility/detail/result_of_iterate.hpp
==============================================================================
--- trunk/boost/utility/detail/result_of_iterate.hpp Wed Jul 3 18:02:30 2013 (r84948)
+++ trunk/boost/utility/detail/result_of_iterate.hpp 2013-07-03 18:14:27 EDT (Wed, 03 Jul 2013) (r84949)
@@ -38,10 +38,25 @@
 #endif
 
 #ifdef BOOST_RESULT_OF_USE_DECLTYPE
+template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
+struct result_of<F(BOOST_RESULT_OF_ARGS)>
+ : detail::cpp0x_result_of<F(BOOST_RESULT_OF_ARGS)> { };
+#endif // BOOST_RESULT_OF_USE_DECLTYPE
+
+#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
+template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
+struct result_of<F(BOOST_RESULT_OF_ARGS)>
+ : mpl::if_<mpl::or_<detail::has_result_type<F>, detail::has_result<F> >,
+ tr1_result_of<F(BOOST_RESULT_OF_ARGS)>,
+ detail::cpp0x_result_of<F(BOOST_RESULT_OF_ARGS)> >::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 {
 
-// Uses declval following N3225 20.7.7.6 when F is not a pointer.
 template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
-struct result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
+struct cpp0x_result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
     : mpl::if_<
           is_member_function_pointer<F>
         , detail::tr1_result_of_impl<
@@ -54,8 +69,6 @@
>::type
 {};
 
-namespace detail {
-
 #ifdef BOOST_NO_SFINAE_EXPR
 
 template<typename F>
@@ -139,7 +152,7 @@
 
 } // namespace detail
 
-#else // defined(BOOST_RESULT_OF_USE_DECLTYPE)
+#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<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>

Modified: trunk/boost/utility/result_of.hpp
==============================================================================
--- trunk/boost/utility/result_of.hpp Wed Jul 3 18:02:30 2013 (r84948)
+++ trunk/boost/utility/result_of.hpp 2013-07-03 18:14:27 EDT (Wed, 03 Jul 2013) (r84949)
@@ -38,18 +38,27 @@
 
 // Use the decltype-based version of result_of by default if the compiler
 // supports N3276 <http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2011/n3276.pdf>.
-// 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 @@
 
 BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
 
+BOOST_MPL_HAS_XXX_TEMPLATE_DEF(result)
+
 template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
 
+template<typename F> 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

Modified: trunk/libs/utility/test/result_of_test.cpp
==============================================================================
--- trunk/libs/utility/test/result_of_test.cpp Wed Jul 3 18:02:30 2013 (r84948)
+++ trunk/libs/utility/test/result_of_test.cpp 2013-07-03 18:14:27 EDT (Wed, 03 Jul 2013) (r84949)
@@ -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 <boost/config.hpp>
 
 // For more information, see http://www.boost.org/libs/utility
@@ -190,7 +196,7 @@
   BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile int_result_of_template<void>(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<result_of<int_result_of(void)>::type, int>::value));
   BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of(void)>::type, int>::value));
@@ -273,7 +279,7 @@
   BOOST_STATIC_ASSERT((is_same<tr1_result_of<pf_t(int)>::type, int>::value));
   BOOST_STATIC_ASSERT((is_same<tr1_result_of<pf_t const(int)>::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<result_of<no_result_type_or_result(double)>::type, short>::value));
   BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(double)>::type, cv_overload_check<const short> >::value));
   BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(double)>::type, cv_overload_check<volatile short> >::value));
@@ -301,7 +307,7 @@
 #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)

Modified: trunk/libs/utility/utility.htm
==============================================================================
--- trunk/libs/utility/utility.htm Wed Jul 3 18:02:30 2013 (r84948)
+++ trunk/libs/utility/utility.htm 2013-07-03 18:14:27 EDT (Wed, 03 Jul 2013) (r84949)
@@ -259,6 +259,46 @@
                 represent the return type of
                 <code>operator()</code> given a call expression.</p>
 
+ <p>Additionally, <code>boost::result_of</code>
+ provides a third mode of operation, which some users
+ may find convenient. When
+ <code>BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK</code>
+ is defined, <code>boost::result_of</code> behaves as
+ follows. If the function object has a member
+ type <code>result_type</code> or member
+ template <code>result&lt;&gt;</code>, then
+ <code>boost::result_of</code> will use the TR1
+ protocol. Otherwise,
+ <code>boost::result_of</code> will
+ use <code>decltype</code>. Using TR1 with
+ a <code>declytpe</code> fallback may workaround
+ certain problems at the cost of portability. For
+ example:
+ <ul>
+ <li>Deficient compiler: If your code
+ requires <code>boost::result_of</code> to work
+ with incomplete return types but your
+ compiler's <code>decltype</code> 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.</li>
+
+ <li>Deficient legacy code: If your existing TR1
+ function object advertises a different type than
+ the actual result type deduced
+ by <code>decltype</code>, then using TR1 with a
+ <code>decltype</code> 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 <code>boost::result_of</code> and TR1.</li>
+ </ul>
+
                 <a name="BOOST_NO_RESULT_OF"></a>
                 <p>This implementation of <code>result_of</code>
                 requires class template partial specialization, the


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk