diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp
index 1ec857a..f0b7a16 100644
--- a/include/boost/utility/detail/result_of_iterate.hpp
+++ b/include/boost/utility/detail/result_of_iterate.hpp
@@ -66,7 +66,7 @@ struct cpp0x_result_of_impl
} // 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
: tr1_result_of { };
#endif
-#endif // defined(BOOST_NO_DECLTYPE)
+#endif // !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE)
#undef BOOST_RESULT_OF_ARGS
diff --git a/include/boost/utility/result_of.hpp b/include/boost/utility/result_of.hpp
index 41cc176..8a07081 100644
--- a/include/boost/utility/result_of.hpp
+++ b/include/boost/utility/result_of.hpp
@@ -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 .
+// 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 struct result_of;
diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp
index 39f6c3b..49ecf33 100644
--- a/test/result_of_test.cpp
+++ b/test/result_of_test.cpp
@@ -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
// For more information, see http://www.boost.org/libs/utility
#include
@@ -62,6 +62,9 @@ struct int_result_type_and_float_result_of_and_char_return_template
char operator()(char);
};
+template
+struct cv_overload_check {};
+
struct result_of_member_function_template
{
template struct result;
@@ -69,13 +72,13 @@ struct result_of_member_function_template
template struct result { typedef That type; };
template typename result::type operator()(T);
- template struct result { typedef const That type; };
+ template struct result { typedef cv_overload_check type; };
template typename result::type operator()(T) const;
- template struct result { typedef volatile That type; };
+ template struct result { typedef cv_overload_check type; };
template typename result::type operator()(T) volatile;
- template struct result { typedef const volatile That type; };
+ template struct result { typedef cv_overload_check type; };
template typename result::type operator()(T) const volatile;
template struct result { typedef That & type; };
@@ -91,13 +94,16 @@ struct result_of_member_function_template
template typename result::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 operator()(double) const;
+ cv_overload_check operator()(double) volatile;
+ cv_overload_check operator()(double) const volatile;
+ int operator()();
+ cv_overload_check operator()() const;
+ cv_overload_check operator()() volatile;
+ cv_overload_check operator()() const volatile;
#if !defined(BOOST_NO_RVALUE_REFERENCES)
short operator()(int&&);
int operator()(int&);
@@ -106,13 +112,16 @@ struct no_result_type_or_result_of
};
template
-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 operator()(double) const;
+ cv_overload_check operator()(double) volatile;
+ cv_overload_check operator()(double) const volatile;
+ int operator()();
+ cv_overload_check operator()() const;
+ cv_overload_check operator()() volatile;
+ cv_overload_check operator()() const volatile;
#if !defined(BOOST_NO_RVALUE_REFERENCES)
short operator()(int&&);
int operator()(int&);
@@ -157,7 +166,7 @@ int main()
// 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::type, int>::value));
BOOST_STATIC_ASSERT((is_same::type, int>::value));
BOOST_STATIC_ASSERT((is_same(void)>::type, int>::value));
@@ -169,14 +178,11 @@ int main()
BOOST_STATIC_ASSERT((is_same(void)>::type, void>::value));
#endif
- BOOST_STATIC_ASSERT((is_same::type, int>::value));
- BOOST_STATIC_ASSERT((is_same(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::type, char>::value));
BOOST_STATIC_ASSERT((is_same(char)>::type, char>::value));
#else
@@ -184,6 +190,9 @@ int main()
BOOST_STATIC_ASSERT((is_same(char)>::type, int>::value));
#endif
+ BOOST_STATIC_ASSERT((is_same::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same(char)>::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));
@@ -207,18 +216,18 @@ int main()
BOOST_STATIC_ASSERT((is_same::type, int>::value));
BOOST_STATIC_ASSERT((is_same::type, double>::value));
- BOOST_STATIC_ASSERT((is_same::type, const double>::value));
- BOOST_STATIC_ASSERT((is_same::type, volatile double>::value));
- BOOST_STATIC_ASSERT((is_same::type, const volatile 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));
BOOST_STATIC_ASSERT((is_same::type, double>::value));
- BOOST_STATIC_ASSERT((is_same::type, const double>::value));
- BOOST_STATIC_ASSERT((is_same::type, volatile double>::value));
- BOOST_STATIC_ASSERT((is_same::type, const volatile 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));
@@ -231,24 +240,31 @@ int main()
BOOST_STATIC_ASSERT((is_same::type, int>::value));
BOOST_STATIC_ASSERT((is_same::type,int>::value));
-#if !defined(BOOST_NO_DECLTYPE)
- BOOST_STATIC_ASSERT((is_same::type, int>::value));
- BOOST_STATIC_ASSERT((is_same::type, unsigned int>::value));
- BOOST_STATIC_ASSERT((is_same::type, short>::value));
- BOOST_STATIC_ASSERT((is_same::type, unsigned short>::value));
- BOOST_STATIC_ASSERT((is_same::type, const unsigned short>::value));
- BOOST_STATIC_ASSERT((is_same(double)>::type, int>::value));
- BOOST_STATIC_ASSERT((is_same(void)>::type, unsigned int>::value));
- BOOST_STATIC_ASSERT((is_same(double)>::type, short>::value));
- BOOST_STATIC_ASSERT((is_same(void)>::type, unsigned short>::value));
- BOOST_STATIC_ASSERT((is_same(void)>::type, const unsigned short>::value));
+#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
+ 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));
+ BOOST_STATIC_ASSERT((is_same::type, cv_overload_check >::value));
+ BOOST_STATIC_ASSERT((is_same::type, int>::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(double)>::type, short>::value));
+ BOOST_STATIC_ASSERT((is_same(double)>::type, cv_overload_check >::value));
+ BOOST_STATIC_ASSERT((is_same(double)>::type, cv_overload_check >::value));
+ BOOST_STATIC_ASSERT((is_same(double)>::type, cv_overload_check >::value));
+ BOOST_STATIC_ASSERT((is_same(void)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value));
+ BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value));
+ BOOST_STATIC_ASSERT((is_same(void)>::type, cv_overload_check >::value));
#if !defined(BOOST_NO_RVALUE_REFERENCES)
- BOOST_STATIC_ASSERT((is_same::type, short>::value));
- BOOST_STATIC_ASSERT((is_same::type, int>::value));
- BOOST_STATIC_ASSERT((is_same::type, long>::value));
- BOOST_STATIC_ASSERT((is_same(int&&)>::type, short>::value));
- BOOST_STATIC_ASSERT((is_same(int&)>::type, int>::value));
- BOOST_STATIC_ASSERT((is_same(int const&)>::type, long>::value));
+ BOOST_STATIC_ASSERT((is_same::type, short>::value));
+ BOOST_STATIC_ASSERT((is_same::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same::type, long>::value));
+ BOOST_STATIC_ASSERT((is_same(int&&)>::type, short>::value));
+ BOOST_STATIC_ASSERT((is_same(int&)>::type, int>::value));
+ BOOST_STATIC_ASSERT((is_same(int const&)>::type, long>::value));
#endif
#endif
diff --git a/utility.htm b/utility.htm
index e2cbfd7..e4e79a3 100644
--- a/utility.htm
+++ b/utility.htm
@@ -161,14 +161,12 @@ void f() {
resides in the header <boost/utility/result_of.hpp>
.
- If your compiler supports decltype
,
- then you can enable automatic result type deduction by
- defining the macro BOOST_RESULT_OF_USE_DECLTYPE
,
- as in the following example.
+ If your compiler's support for decltype
is
+ adequate, result_of
automatically uses it to
+ deduce the result type of your callable object.
- #define BOOST_RESULT_OF_USE_DECLTYPE
-#include <boost/utility/result_of.hpp>
+ #include <boost/utility/result_of.hpp>
struct functor {
template<class T>
@@ -180,21 +178,29 @@ struct functor {
typedef boost::result_of<
functor(int)
->::type type;
+>::type type; // type is int
- If decltype
is not enabled,
+
You can test whether result_of
is 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,
then automatic result type deduction of function
objects is not possible. Instead, result_of
uses the following protocol to allow the programmer to
specify a type. When F
is a class type with a
member type result_type
,
result_of<F(T1, T2, ...,
- TN)>
is
+ TN)>::type is
F::result_type
. When F
does
not contain result_type
,
result_of<F(T1, T2, ...,
- TN)>
is F::result<F(T1,
+ TN)>::type
is F::result<F(T1,
T2, ..., TN)>::type
when
N > 0
or void
when N = 0
. Note that it is the
@@ -221,22 +227,29 @@ typedef boost::result_of<
typedef boost::result_of<
functor(int)
->::type type;
+>::type type; // type is int
-
In a future
- release, BOOST_RESULT_OF_USE_DECLTYPE
- may be enabled by default on compilers that
- support decltype
, so if you use the above
- protocol please take care to ensure that
- the result_type
- and result<>
members accurately
- represent the result type. If you wish to continue to
+
Since decltype
is a new language
+ feature recently standardized in C++11,
+ if you are writing a function object
+ to be used with result_of
, for
+ maximum portability, you might consider following
+ the above protocol even if your compiler has
+ proper decltype
support. If you wish to continue to
use the protocol on compilers that
- support decltype
,
- use boost::tr1_result_of
, which is also
- defined
- in <boost/utility/result_of.hpp>
.
+ support decltype
, there are two options:
+ You can use boost::tr1_result_of
, which is also
+ defined in <boost/utility/result_of.hpp>
.
+ Alternatively, you can define the macro
+ BOOST_RESULT_OF_USE_TR1
, which causes
+ result_of
to use the protocol described
+ above instead of decltype
. If you choose to
+ follow the protocol, take care to ensure that the
+ result_type
and
+ result<>
members accurately
+ represent the return type of
+ operator()
.
This implementation of result_of
@@ -253,7 +266,7 @@ typedef boost::result_of<
N1836,
or, for motivation and design rationale,
the result_of
proposal.
- Contributed by Doug Gregor.
+ Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others
Class templates for the Base-from-Member Idiom
See separate documentation.