added new result_of mode that uses TR1 with a decltype fallback as suggested by Nathan Crookston; fixes #7753

[SVN r84949]
This commit is contained in:
Daniel Walker 2013-07-03 22:14:27 +00:00
parent 9baf33dd16
commit 15021632dc
4 changed files with 89 additions and 17 deletions

View File

@ -38,10 +38,25 @@ struct tr1_result_of<F(BOOST_RESULT_OF_ARGS)>
#endif
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
// Uses declval following N3225 20.7.7.6 when F is not a pointer.
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
struct result_of<F(BOOST_RESULT_OF_ARGS)>
: detail::cpp0x_result_of<F(BOOST_RESULT_OF_ARGS)> { };
#endif // BOOST_RESULT_OF_USE_DECLTYPE
#ifdef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<F(BOOST_RESULT_OF_ARGS)>
: mpl::if_<mpl::or_<detail::has_result_type<F>, detail::has_result<F> >,
tr1_result_of<F(BOOST_RESULT_OF_ARGS)>,
detail::cpp0x_result_of<F(BOOST_RESULT_OF_ARGS)> >::type { };
#endif // BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
namespace detail {
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct cpp0x_result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
: mpl::if_<
is_member_function_pointer<F>
, detail::tr1_result_of_impl<
@ -54,8 +69,6 @@ struct result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
>::type
{};
namespace detail {
#ifdef BOOST_NO_SFINAE_EXPR
template<typename F>
@ -139,7 +152,7 @@ struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)),
} // namespace detail
#else // defined(BOOST_RESULT_OF_USE_DECLTYPE)
#else // defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>

View File

@ -38,20 +38,29 @@
// 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.
// The user can force the choice by defining BOOST_RESULT_OF_USE_DECLTYPE,
// BOOST_RESULT_OF_USE_TR1, or BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK but not more than one!
#if (defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1)) || \
(defined(BOOST_RESULT_OF_USE_DECLTYPE) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)) || \
(defined(BOOST_RESULT_OF_USE_TR1) && defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK))
# error More than one of BOOST_RESULT_OF_USE_DECLTYPE, BOOST_RESULT_OF_USE_TR1 and \
BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK cannot be defined at the same time.
#endif
#if defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK) && defined(BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE)
# error Cannot fallback to decltype if BOOST_MPL_CFG_NO_HAS_XXX_TEMPLATE is not defined.
#endif
#ifndef BOOST_RESULT_OF_USE_TR1
# ifndef BOOST_RESULT_OF_USE_DECLTYPE
# ifndef BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK
# ifndef BOOST_NO_CXX11_DECLTYPE_N3276 // this implies !defined(BOOST_NO_CXX11_DECLTYPE)
# define BOOST_RESULT_OF_USE_DECLTYPE
# else
# define BOOST_RESULT_OF_USE_TR1
# endif
# endif
# endif
#endif
namespace boost {
@ -64,8 +73,12 @@ namespace detail {
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
BOOST_MPL_HAS_XXX_TEMPLATE_DEF(result)
template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
template<typename F> struct cpp0x_result_of;
#ifdef BOOST_NO_SFINAE_EXPR
// There doesn't seem to be any other way to turn this off such that the presence of

View File

@ -5,6 +5,12 @@
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Examples:
// To run the default test:
// $ cd libs/utility/test && bjam
// To test decltype on g++ 2.7:
// $ cd libs/utility/test && bjam cxxflags="-std=c++11 -D BOOST_RESULT_OF_USE_DECLTYPE"
#include <boost/config.hpp>
// For more information, see http://www.boost.org/libs/utility
@ -190,7 +196,7 @@ int main()
BOOST_STATIC_ASSERT((is_same<tr1_result_of<volatile int_result_of_template<void>(void)>::type, void>::value));
// Prior to decltype, result_of could not deduce the return type
// nullary function objects unless they exposed a result_type.
// of nullary function objects unless they exposed a result_type.
#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));
@ -273,7 +279,7 @@ int main()
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_RESULT_OF_USE_DECLTYPE)
#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
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));
@ -301,7 +307,7 @@ int main()
#endif
#endif
#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
#if defined(BOOST_RESULT_OF_USE_DECLTYPE) || defined(BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK)
int i = 123;
sfinae_test(sfinae_test_f, i);
#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE)

View File

@ -259,6 +259,46 @@ typedef boost::result_of&lt;
represent the return type of
<code>operator()</code> given a call expression.</p>
<p>Additionally, <code>boost::result_of</code>
provides a third mode of operation, which some users
may find convenient. When
<code>BOOST_RESULT_OF_USE_TR1_WITH_DECLTYPE_FALLBACK</code>
is defined, <code>boost::result_of</code> behaves as
follows. If the function object has a member
type <code>result_type</code> or member
template <code>result&lt;&gt;</code>, then
<code>boost::result_of</code> will use the TR1
protocol. Otherwise,
<code>boost::result_of</code> will
use <code>decltype</code>. Using TR1 with
a <code>declytpe</code> fallback may workaround
certain problems at the cost of portability. For
example:
<ul>
<li>Deficient compiler: If your code
requires <code>boost::result_of</code> to work
with incomplete return types but your
compiler's <code>decltype</code> implementation
does not support incomplete return types, then you
can use the TR1 protocol as a workaround. Support
for incomplete return types was added late in the
C++11 standardization process
(see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3276.pdf">N3276</a>)
and is not implemented by some compilers.</li>
<li>Deficient legacy code: If your existing TR1
function object advertises a different type than
the actual result type deduced
by <code>decltype</code>, then using TR1 with a
<code>decltype</code> fallback will allow you to
work with both your existing TR1 function objects
and new C++11 function object. This situation
could occur if your legacy function objects
misused the TR1 protocol. See the documentation on
known <a href="#result_of_tr1_diff">differences</a>
between <code>boost::result_of</code> and TR1.</li>
</ul>
<a name="BOOST_NO_RESULT_OF"></a>
<p>This implementation of <code>result_of</code>
requires class template partial specialization, the