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.