Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r80355 - in branches/release: . boost boost/utility boost/utility/detail libs libs/utility libs/utility/test
From: eric_at_[hidden]
Date: 2012-09-01 19:12:33


Author: eric_niebler
Date: 2012-09-01 19:12:32 EDT (Sat, 01 Sep 2012)
New Revision: 80355
URL: http://svn.boost.org/trac/boost/changeset/80355

Log:
boost::result_of uses decltype on compilers that implement N3276, merges [77905], [78195], [80352] from trunk
Properties modified:
   branches/release/ (props changed)
   branches/release/boost/ (props changed)
   branches/release/boost/utility/ (props changed)
   branches/release/libs/ (props changed)
   branches/release/libs/utility/ (props changed)
Text files modified:
   branches/release/boost/utility/detail/result_of_iterate.hpp | 4
   branches/release/boost/utility/result_of.hpp | 18 ++++++
   branches/release/libs/utility/test/result_of_test.cpp | 104 +++++++++++++++++++++++----------------
   branches/release/libs/utility/utility.htm | 61 ++++++++++++++---------
   4 files changed, 117 insertions(+), 70 deletions(-)

Modified: branches/release/boost/utility/detail/result_of_iterate.hpp
==============================================================================
--- branches/release/boost/utility/detail/result_of_iterate.hpp (original)
+++ branches/release/boost/utility/detail/result_of_iterate.hpp 2012-09-01 19:12:32 EDT (Sat, 01 Sep 2012)
@@ -66,7 +66,7 @@
 
 } // namespace detail
 
-#else // defined(BOOST_NO_DECLTYPE)
+#else // !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE)
 
 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
 template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
@@ -75,7 +75,7 @@
     : tr1_result_of<F(BOOST_RESULT_OF_ARGS)> { };
 #endif
 
-#endif // defined(BOOST_NO_DECLTYPE)
+#endif // !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE)
 
 #undef BOOST_RESULT_OF_ARGS
 

Modified: branches/release/boost/utility/result_of.hpp
==============================================================================
--- branches/release/boost/utility/result_of.hpp (original)
+++ branches/release/boost/utility/result_of.hpp 2012-09-01 19:12:32 EDT (Sat, 01 Sep 2012)
@@ -30,6 +30,24 @@
 # define BOOST_RESULT_OF_NUM_ARGS 10
 #endif
 
+// 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.
+#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
+# endif
+# endif
+#endif
+
 namespace boost {
 
 template<typename F> struct result_of;

Modified: branches/release/libs/utility/test/result_of_test.cpp
==============================================================================
--- branches/release/libs/utility/test/result_of_test.cpp (original)
+++ branches/release/libs/utility/test/result_of_test.cpp 2012-09-01 19:12:32 EDT (Sat, 01 Sep 2012)
@@ -5,7 +5,7 @@
 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
 // http://www.boost.org/LICENSE_1_0.txt)
 
-#define BOOST_RESULT_OF_USE_DECLTYPE
+#include <boost/config.hpp>
 
 // For more information, see http://www.boost.org/libs/utility
 #include <boost/utility/result_of.hpp>
@@ -62,6 +62,9 @@
   char operator()(char);
 };
 
+template<typename T>
+struct cv_overload_check {};
+
 struct result_of_member_function_template
 {
   template<typename F> struct result;
@@ -69,13 +72,13 @@
   template<typename This, typename That> struct result<This(That)> { typedef That type; };
   template<class T> typename result<result_of_member_function_template(T)>::type operator()(T);
 
- template<typename This, typename That> struct result<const This(That)> { typedef const That type; };
+ template<typename This, typename That> struct result<const This(That)> { typedef cv_overload_check<const That> type; };
   template<class T> typename result<const result_of_member_function_template(T)>::type operator()(T) const;
 
- template<typename This, typename That> struct result<volatile This(That)> { typedef volatile That type; };
+ template<typename This, typename That> struct result<volatile This(That)> { typedef cv_overload_check<volatile That> type; };
   template<class T> typename result<volatile result_of_member_function_template(T)>::type operator()(T) volatile;
 
- template<typename This, typename That> struct result<const volatile This(That)> { typedef const volatile That type; };
+ template<typename This, typename That> struct result<const volatile This(That)> { typedef cv_overload_check<const volatile That> type; };
   template<class T> typename result<const volatile result_of_member_function_template(T)>::type operator()(T) const volatile;
 
   template<typename This, typename That> struct result<This(That &, That)> { typedef That & type; };
@@ -91,13 +94,16 @@
   template<class T> typename result<result_of_member_function_template(T const volatile &, T)>::type operator()(T const volatile &, T);
 };
 
-struct no_result_type_or_result_of
+struct no_result_type_or_result
 {
- int operator()(double);
- short operator()(double) const;
- unsigned int operator()();
- unsigned short operator()() volatile;
- const unsigned short operator()() const volatile;
+ short operator()(double);
+ cv_overload_check<const short> operator()(double) const;
+ cv_overload_check<volatile short> operator()(double) volatile;
+ cv_overload_check<const volatile short> operator()(double) const volatile;
+ int operator()();
+ cv_overload_check<const int> operator()() const;
+ cv_overload_check<volatile int> operator()() volatile;
+ cv_overload_check<const volatile int> operator()() const volatile;
 #if !defined(BOOST_NO_RVALUE_REFERENCES)
   short operator()(int&&);
   int operator()(int&);
@@ -106,13 +112,16 @@
 };
 
 template<typename T>
-struct no_result_type_or_result_of_template
+struct no_result_type_or_result_template
 {
- int operator()(double);
- short operator()(double) const;
- unsigned int operator()();
- unsigned short operator()() volatile;
- const unsigned short operator()() const volatile;
+ short operator()(double);
+ cv_overload_check<const short> operator()(double) const;
+ cv_overload_check<volatile short> operator()(double) volatile;
+ cv_overload_check<const volatile short> operator()(double) const volatile;
+ int operator()();
+ cv_overload_check<const int> operator()() const;
+ cv_overload_check<volatile int> operator()() volatile;
+ cv_overload_check<const volatile int> operator()() const volatile;
 #if !defined(BOOST_NO_RVALUE_REFERENCES)
   short operator()(int&&);
   int operator()(int&);
@@ -157,7 +166,7 @@
 
   // Prior to decltype, result_of could not deduce the return type
   // nullary function objects unless they exposed a result_type.
-#if !defined(BOOST_NO_DECLTYPE)
+#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));
   BOOST_STATIC_ASSERT((is_same<result_of<int_result_of_template<void>(void)>::type, int>::value));
@@ -169,14 +178,11 @@
   BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of_template<void>(void)>::type, void>::value));
 #endif
 
- BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, int>::value));
- BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
-
   // Prior to decltype, result_of ignored a nested result<> if
   // result_type was defined. After decltype, result_of deduces the
   // actual return type of the function object, ignoring both
   // result<> and result_type.
-#if !defined(BOOST_NO_DECLTYPE)
+#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
   BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, char>::value));
   BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, char>::value));
 #else
@@ -184,6 +190,9 @@
   BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
 #endif
 
+ BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return(char)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<tr1_result_of<int_result_type_and_float_result_of_and_char_return_template<void>(char)>::type, int>::value));
+
   BOOST_STATIC_ASSERT((is_same<result_of<func_ptr(char, float)>::type, int>::value));
   BOOST_STATIC_ASSERT((is_same<result_of<func_ref(char, float)>::type, int>::value));
   BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_0()>::type, int>::value));
@@ -207,18 +216,18 @@
   BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(void)>::type, int>::value));
 
   BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(double)>::type, double>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<const result_of_member_function_template(double)>::type, const double>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<volatile result_of_member_function_template(double)>::type, volatile double>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<const volatile result_of_member_function_template(double)>::type, const volatile double>::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value));
   BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int &, int)>::type, int &>::value));
   BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value));
   BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value));
   BOOST_STATIC_ASSERT((is_same<result_of<result_of_member_function_template(int const volatile &, int)>::type, int const volatile &>::value));
 
   BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(double)>::type, double>::value));
- BOOST_STATIC_ASSERT((is_same<tr1_result_of<const result_of_member_function_template(double)>::type, const double>::value));
- BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile result_of_member_function_template(double)>::type, volatile double>::value));
- BOOST_STATIC_ASSERT((is_same<tr1_result_of<const volatile result_of_member_function_template(double)>::type, const volatile double>::value));
+ BOOST_STATIC_ASSERT((is_same<tr1_result_of<const result_of_member_function_template(double)>::type, cv_overload_check<const double> >::value));
+ BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile result_of_member_function_template(double)>::type, cv_overload_check<volatile double> >::value));
+ BOOST_STATIC_ASSERT((is_same<tr1_result_of<const volatile result_of_member_function_template(double)>::type, cv_overload_check<const volatile double> >::value));
   BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int &, int)>::type, int &>::value));
   BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int const &, int)>::type, int const &>::value));
   BOOST_STATIC_ASSERT((is_same<tr1_result_of<result_of_member_function_template(int volatile &, int)>::type, int volatile &>::value));
@@ -231,24 +240,31 @@
   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_NO_DECLTYPE)
- BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of(double)>::type, int>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of(void)>::type, unsigned int>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_of(double)>::type, short>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_of(void)>::type, unsigned short>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_of(void)>::type, const unsigned short>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(double)>::type, int>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(void)>::type, unsigned int>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_of_template<void>(double)>::type, short>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_of_template<void>(void)>::type, unsigned short>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_of_template<void>(void)>::type, const unsigned short>::value));
+#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
+ 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));
+ BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(double)>::type, cv_overload_check<const volatile short> >::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(void)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result(void)>::type, cv_overload_check<const int> >::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result(void)>::type, cv_overload_check<volatile int> >::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result(void)>::type, cv_overload_check<const volatile int> >::value));
+
+ BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(double)>::type, short>::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(double)>::type, cv_overload_check<const short> >::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(double)>::type, cv_overload_check<volatile short> >::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_template<void>(double)>::type, cv_overload_check<const volatile short> >::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(void)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<const no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const int> >::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<volatile int> >::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<const volatile no_result_type_or_result_template<void>(void)>::type, cv_overload_check<const volatile int> >::value));
 #if !defined(BOOST_NO_RVALUE_REFERENCES)
- BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of(int&&)>::type, short>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of(int&)>::type, int>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of(int const&)>::type, long>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(int&&)>::type, short>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(int&)>::type, int>::value));
- BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_of_template<void>(int const&)>::type, long>::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&&)>::type, short>::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int&)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result(int const&)>::type, long>::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&&)>::type, short>::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int&)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same<result_of<no_result_type_or_result_template<void>(int const&)>::type, long>::value));
 #endif
 #endif
 

Modified: branches/release/libs/utility/utility.htm
==============================================================================
--- branches/release/libs/utility/utility.htm (original)
+++ branches/release/libs/utility/utility.htm 2012-09-01 19:12:32 EDT (Sat, 01 Sep 2012)
@@ -161,14 +161,12 @@
                 resides in the header <code>&lt;<a
                 href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>&gt;</code>.</p>
 
- <p>If your compiler supports <code>decltype</code>,
- then you can enable automatic result type deduction by
- defining the macro <code>BOOST_RESULT_OF_USE_DECLTYPE</code>,
- as in the following example.</p>
+ <p>If your compiler's support for <code>decltype</code> is
+ adequate, <code>result_of</code> automatically uses it to
+ deduce the result type of your callable object.</p>
 
                 <blockquote>
- <pre>#define BOOST_RESULT_OF_USE_DECLTYPE
-#include &lt;boost/utility/result_of.hpp&gt;
+ <pre>#include &lt;boost/utility/result_of.hpp&gt;
 
 struct functor {
     template&lt;class T&gt;
@@ -180,21 +178,29 @@
 
 typedef boost::result_of&lt;
     functor(int)
-&gt;::type type;</pre>
+&gt;::type type; // type is int</pre>
                 </blockquote>
 
- <p>If <code>decltype</code> is not enabled,
+ <p>You can test whether <code>result_of</code> is using
+ <code>decltype</code> by checking if the macro
+ <code>BOOST_RESULT_OF_USE_DECLTYPE</code> is defined after
+ including <code>result_of.hpp</code>. You can also force
+ <code>result_of</code> to use <code>decltype</code> by
+ defining <code>BOOST_RESULT_OF_USE_DECLTYPE</code> prior
+ to including <code>result_of.hpp</code>.</p>
+
+ <p>If <code>decltype</code> is not used,
                 then automatic result type deduction of function
                 objects is not possible. Instead, <code>result_of</code>
                 uses the following protocol to allow the programmer to
                 specify a type. When <code>F</code> is a class type with a
                 member type <code>result_type</code>,
                 <code>result_of&lt;F(T1, T2, ...,
- T<em>N</em>)&gt;</code> is
+ T<em>N</em>)&gt;::type</code> is
                 <code>F::result_type</code>. When <code>F</code> does
                 not contain <code>result_type</code>,
                 <code>result_of&lt;F(T1, T2, ...,
- T<em>N</em>)&gt;</code> is <code>F::result&lt;F(T1,
+ T<em>N</em>)&gt;::type</code> is <code>F::result&lt;F(T1,
                 T2, ..., T<em>N</em>)&gt;::type</code> when
                 <code><em>N</em> &gt; 0</code> or <code>void</code>
                 when <code><em>N</em> = 0</code>. Note that it is the
@@ -221,22 +227,29 @@
 
 typedef boost::result_of&lt;
     functor(int)
-&gt;::type type;</pre>
+&gt;::type type; // type is int</pre>
                 </blockquote>
 
- <p>In a future
- release, <code>BOOST_RESULT_OF_USE_DECLTYPE</code>
- may be enabled by default on compilers that
- support <code>decltype</code>, so if you use the above
- protocol please take care to ensure that
- the <code>result_type</code>
- and <code>result&lt;&gt;</code> members accurately
- represent the result type. If you wish to continue to
+ <p>Since <code>decltype</code> is a new language
+ feature recently standardized in C++11,
+ if you are writing a function object
+ to be used with <code>result_of</code>, for
+ maximum portability, you might consider following
+ the above protocol even if your compiler has
+ proper <code>decltype</code> support. If you wish to continue to
                 use the protocol on compilers that
- support <code>decltype</code>,
- use <code>boost::tr1_result_of</code>, which is also
- defined
- in <code>&lt;boost/utility/result_of.hpp&gt;</code>.</p>
+ support <code>decltype</code>, there are two options:
+ You can use <code>boost::tr1_result_of</code>, which is also
+ defined in <code>&lt;boost/utility/result_of.hpp&gt;</code>.
+ Alternatively, you can define the macro
+ <code>BOOST_RESULT_OF_USE_TR1</code>, which causes
+ <code>result_of</code> to use the protocol described
+ above instead of <code>decltype</code>. If you choose to
+ follow the protocol, take care to ensure that the
+ <code>result_type</code> and
+ <code>result&lt;&gt;</code> members accurately
+ represent the return type of
+ <code>operator()</code>.</p>
 
                 <a name="BOOST_NO_RESULT_OF"></a>
                 <p>This implementation of <code>result_of</code>
@@ -253,7 +266,7 @@
                 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">N1836</a>,
                 or, for motivation and design rationale,
                 the <code>result_of</code> proposal.</p>
- Contributed by Doug Gregor.</p>
+ <p>Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others</p>
 
                 <h2>Class templates for the Base-from-Member Idiom</h2>
                 <p>See separate documentation.</p>


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