From 2637dfcc592c0a1e985ac889e1e589fd469801d2 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Wed, 11 Apr 2012 00:05:56 +0000 Subject: [PATCH] result_of uses decltype on compilers that implement N3276 [SVN r77903] --- .../utility/detail/result_of_iterate.hpp | 6 +-- include/boost/utility/result_of.hpp | 18 +++++++ utility.htm | 53 ++++++++++++------- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/include/boost/utility/detail/result_of_iterate.hpp b/include/boost/utility/detail/result_of_iterate.hpp index 29fcd78..5cf30b6 100644 --- a/include/boost/utility/detail/result_of_iterate.hpp +++ b/include/boost/utility/detail/result_of_iterate.hpp @@ -38,7 +38,7 @@ struct tr1_result_of (boost::detail::has_result_type::value)> >::type { }; #endif -#if !defined(BOOST_NO_DECLTYPE) && defined(BOOST_RESULT_OF_USE_DECLTYPE) +#ifdef BOOST_RESULT_OF_USE_DECLTYPE // Uses declval following N3225 20.7.7.6 when F is not a pointer. template } // namespace detail -#else // defined(BOOST_NO_DECLTYPE) +#else // 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_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 77c26fe..93b7264 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 16 #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/utility.htm b/utility.htm index 474a338..65ead22 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.

-
#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 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 +

If you are writing a reusable function object + that should work with result_of, for + maximum portability, you might consider following + the above protocol even if your compiler has + proper decltype support. If you do, + take care to ensure that the + result_type and + result<> members accurately + represent the return type of + operator().

+ +

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>.

+ in <boost/utility/result_of.hpp>. You can also define the macro + BOOST_RESULT_OF_USE_TR1, which causes + result_of to use the convention described + above instead of decltype.

This implementation of result_of