|
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><<a
href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>></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 <boost/utility/result_of.hpp>
+ <pre>#include <boost/utility/result_of.hpp>
struct functor {
template<class T>
@@ -180,21 +178,29 @@
typedef boost::result_of<
functor(int)
->::type type;</pre>
+>::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<F(T1, T2, ...,
- T<em>N</em>)></code> is
+ T<em>N</em>)>::type</code> is
<code>F::result_type</code>. When <code>F</code> does
not contain <code>result_type</code>,
<code>result_of<F(T1, T2, ...,
- T<em>N</em>)></code> is <code>F::result<F(T1,
+ T<em>N</em>)>::type</code> is <code>F::result<F(T1,
T2, ..., T<em>N</em>)>::type</code> when
<code><em>N</em> > 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<
functor(int)
->::type type;</pre>
+>::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<></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><boost/utility/result_of.hpp></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><boost/utility/result_of.hpp></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<></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