Compare commits

..

10 Commits

Author SHA1 Message Date
Marshall Clow
9dc0cc931d Release 1.52.0
[SVN r81201]
2012-11-05 15:31:58 +00:00
Eric Niebler
b35ef27b35 add missing close tag
[SVN r80835]
2012-10-03 23:09:58 +00:00
Eric Niebler
124f4ea879 result_of: merge [80732] from trunk
[SVN r80746]
2012-09-28 22:21:32 +00:00
Eric Niebler
0f43c44e97 result_of: merge [80636],[80654],[80655],[80656],[80712] from trunk
[SVN r80713]
2012-09-26 18:52:08 +00:00
Eric Niebler
7d8353f46a result_of: merge [80445], [80452], [80535], [80550], [80605], [80608] from trunk
[SVN r80621]
2012-09-21 18:49:46 +00:00
Daniel Walker
1920623a4f merged [80550], allowing users to force result_of to use decltype
[SVN r80551]
2012-09-17 00:16:36 +00:00
John Maddock
c0cca9e8cc Merge changes from Trunk.
Fixes #5790.

[SVN r80433]
2012-09-07 08:49:11 +00:00
Eric Niebler
d63444f22e merge [77702] to release, fixes #6755
[SVN r80359]
2012-09-02 03:42:37 +00:00
Eric Niebler
1f23425baa result_of limit bumped to 16, merge [71769] from trunk
[SVN r80358]
2012-09-02 03:29:41 +00:00
Eric Niebler
a89b0101fc boost::result_of uses decltype on compilers that implement N3276, merges [77905], [78195], [80352] from trunk
[SVN r80355]
2012-09-01 23:12:32 +00:00
5 changed files with 663 additions and 119 deletions

View File

@@ -24,6 +24,7 @@
#include <cstddef>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/detail/workaround.hpp>
@@ -43,20 +44,26 @@ struct ct_imp2<T, true>
typedef const T param_type;
};
template <typename T, bool isp, bool b1>
template <typename T, bool isp, bool b1, bool b2>
struct ct_imp
{
typedef const T& param_type;
};
template <typename T, bool isp>
struct ct_imp<T, isp, true>
template <typename T, bool isp, bool b2>
struct ct_imp<T, isp, true, b2>
{
typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
};
template <typename T, bool b1>
struct ct_imp<T, true, b1>
template <typename T, bool isp, bool b1>
struct ct_imp<T, isp, b1, true>
{
typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
};
template <typename T, bool b1, bool b2>
struct ct_imp<T, true, b1, b2>
{
typedef const T param_type;
};
@@ -79,7 +86,8 @@ public:
typedef typename boost::detail::ct_imp<
T,
::boost::is_pointer<T>::value,
::boost::is_arithmetic<T>::value
::boost::is_arithmetic<T>::value,
::boost::is_enum<T>::value
>::param_type param_type;
};

View File

@@ -5,6 +5,11 @@
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Copyright Daniel Walker, Eric Niebler, Michel Morin 2008-2012.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or
// copy at http://www.boost.org/LICENSE_1_0.txt)
// For more information, see http://www.boost.org/libs/utility
#if !defined(BOOST_PP_IS_ITERATING)
# error Boost result_of - do not include this file!
@@ -18,31 +23,29 @@
#endif
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of<F(BOOST_RESULT_OF_ARGS)>
: mpl::if_<
mpl::or_< is_pointer<F>, is_member_function_pointer<F> >
, boost::detail::tr1_result_of_impl<
typename remove_cv<F>::type,
typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS),
typename remove_cv<F>::type,
typename remove_cv<F>::type(BOOST_RESULT_OF_ARGS),
(boost::detail::has_result_type<F>::value)>
, boost::detail::tr1_result_of_impl<
F,
F(BOOST_RESULT_OF_ARGS),
F(BOOST_RESULT_OF_ARGS),
(boost::detail::has_result_type<F>::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<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
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))>
: mpl::if_<
mpl::or_< is_pointer<F>, is_member_function_pointer<F> >
is_member_function_pointer<F>
, detail::tr1_result_of_impl<
typename remove_cv<F>::type,
typename remove_cv<F>::type,
typename remove_cv<F>::type(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false
>
, detail::cpp0x_result_of_impl<
@@ -53,53 +56,119 @@ struct result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
namespace detail {
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
#ifdef BOOST_NO_SFINAE_EXPR
template<typename F>
struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION());
template<typename R BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
struct BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<R(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T))> {
R operator()(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(), T)) const;
typedef result_of_private_type const &(*pfn_t)(...);
operator pfn_t() const volatile;
};
template<typename F>
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION());
template<typename F>
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<F *>
: BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<F>
{};
template<typename F>
struct BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<F &>
: BOOST_PP_CAT(result_of_callable_fun_2_, BOOST_PP_ITERATION())<F>
{};
template<typename F>
struct BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())
: mpl::eval_if<
is_class<typename remove_reference<F>::type>,
result_of_wrap_callable_class<F>,
mpl::identity<BOOST_PP_CAT(result_of_callable_fun_, BOOST_PP_ITERATION())<typename remove_cv<F>::type> >
>
{};
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), typename T)>
struct BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION()) {
typedef typename BOOST_PP_CAT(result_of_select_call_wrapper_type_, BOOST_PP_ITERATION())<F>::type wrapper_t;
static const bool value = (
sizeof(result_of_no_type) == sizeof(detail::result_of_is_private_type(
(boost::declval<wrapper_t>()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)), result_of_weird_type())
))
);
typedef mpl::bool_<value> type;
};
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), true>
: lazy_enable_if<
BOOST_PP_CAT(result_of_is_callable_, BOOST_PP_ITERATION())<F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), T)>
, cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
>
{};
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
{
typedef decltype(
boost::declval<F>()(
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), declval<T, >() BOOST_PP_INTERCEPT)
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
)
) type;
};
} // namespace detail
#else // BOOST_NO_SFINAE_EXPR
#else // defined(BOOST_NO_DECLTYPE)
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)),
typename result_of_always_void<decltype(
boost::declval<F>()(
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
)
)>::type> {
typedef decltype(
boost::declval<F>()(
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<T, >() BOOST_PP_INTERCEPT)
)
) type;
};
#endif // BOOST_NO_SFINAE_EXPR
} // namespace detail
#else // defined(BOOST_RESULT_OF_USE_DECLTYPE)
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename F BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<F(BOOST_RESULT_OF_ARGS)>
: tr1_result_of<F(BOOST_RESULT_OF_ARGS)> { };
#endif
#endif // defined(BOOST_NO_DECLTYPE)
#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE)
#undef BOOST_RESULT_OF_ARGS
#if BOOST_PP_ITERATION() >= 1
#if BOOST_PP_ITERATION() >= 1
namespace detail {
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of_impl<R (*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
{
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of_impl<R (&)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
{
typedef R type;
};
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T)),
FArgs, false>
@@ -107,8 +176,7 @@ struct tr1_result_of_impl<R (T0::*)
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
const,
@@ -117,8 +185,7 @@ struct tr1_result_of_impl<R (T0::*)
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
volatile,
@@ -127,8 +194,7 @@ struct tr1_result_of_impl<R (T0::*)
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
template<typename R, typename FArgs BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct tr1_result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
const volatile,

View File

@@ -10,24 +10,48 @@
#define BOOST_RESULT_OF_HPP
#include <boost/config.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/preprocessor/facilities/intercept.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/or.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/is_member_function_pointer.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/declval.hpp>
#include <boost/utility/enable_if.hpp>
#ifndef BOOST_RESULT_OF_NUM_ARGS
# define BOOST_RESULT_OF_NUM_ARGS 10
# define BOOST_RESULT_OF_NUM_ARGS 16
#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 {
@@ -41,7 +65,67 @@ namespace detail {
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
template<typename F> struct cpp0x_result_of_impl;
#ifdef BOOST_NO_SFINAE_EXPR
struct result_of_private_type {};
struct result_of_weird_type {
friend result_of_private_type operator,(result_of_private_type, result_of_weird_type);
};
typedef char result_of_yes_type; // sizeof(result_of_yes_type) == 1
typedef char (&result_of_no_type)[2]; // sizeof(result_of_no_type) == 2
template<typename T>
result_of_no_type result_of_is_private_type(T const &);
result_of_yes_type result_of_is_private_type(result_of_private_type);
template<typename C>
struct result_of_callable_class : C {
result_of_callable_class();
typedef result_of_private_type const &(*pfn_t)(...);
operator pfn_t() const volatile;
};
template<typename C>
struct result_of_wrap_callable_class {
typedef result_of_callable_class<C> type;
};
template<typename C>
struct result_of_wrap_callable_class<C const> {
typedef result_of_callable_class<C> const type;
};
template<typename C>
struct result_of_wrap_callable_class<C volatile> {
typedef result_of_callable_class<C> volatile type;
};
template<typename C>
struct result_of_wrap_callable_class<C const volatile> {
typedef result_of_callable_class<C> const volatile type;
};
template<typename C>
struct result_of_wrap_callable_class<C &> {
typedef typename result_of_wrap_callable_class<C>::type &type;
};
template<typename F, bool TestCallability = true> struct cpp0x_result_of_impl;
#else // BOOST_NO_SFINAE_EXPR
template<typename T>
struct result_of_always_void
{
typedef void type;
};
template<typename F, typename Enable = void> struct cpp0x_result_of_impl {};
#endif // BOOST_NO_SFINAE_EXPR
template<typename F>
struct result_of_void_impl

View File

@@ -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 @@ struct int_result_type_and_float_result_of_and_char_return_template
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 @@ struct result_of_member_function_template
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 @@ struct result_of_member_function_template
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 @@ struct no_result_type_or_result_of
};
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&);
@@ -120,6 +129,27 @@ struct no_result_type_or_result_of_template
#endif
};
// sfinae_tests are derived from example code from Joel de Guzman,
// which demonstrated the interaction between result_of and SFINAE.
template <typename F, typename Arg>
typename boost::result_of<F(Arg const&)>::type
sfinae_test(F f, Arg const& arg)
{
return f(arg);
}
template <typename F, typename Arg>
typename boost::result_of<F(Arg&)>::type
sfinae_test(F f, Arg& arg)
{
return f(arg);
}
int sfinae_test_f(int& i)
{
return i;
}
struct X {};
int main()
@@ -130,6 +160,10 @@ int main()
typedef int (&func_ref)(float, double);
typedef int (*func_ptr_0)();
typedef int (&func_ref_0)();
typedef void (*func_ptr_void)(float, double);
typedef void (&func_ref_void)(float, double);
typedef void (*func_ptr_void_0)();
typedef void (&func_ref_void_0)();
typedef int (X::*mem_func_ptr)(float);
typedef int (X::*mem_func_ptr_c)(float) const;
typedef int (X::*mem_func_ptr_v)(float) volatile;
@@ -157,7 +191,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<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 +203,11 @@ int main()
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,41 +215,52 @@ int main()
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));
BOOST_STATIC_ASSERT((is_same<result_of<func_ref_0()>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void(char, float)>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void(char, float)>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr_void_0()>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ref_void_0()>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_c(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_v(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_cv(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_0(X)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<result_of<func_ptr(void)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(char, float)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(char, float)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_0()>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_0()>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void(char, float)>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void(char, float)>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr_void_0()>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref_void_0()>::type, void>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_c(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_v(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_cv(X,char)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<mem_func_ptr_0(X)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ptr(void)>::type, int>::value));
BOOST_STATIC_ASSERT((is_same<tr1_result_of<func_ref(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,26 +273,38 @@ 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_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
#if defined(BOOST_RESULT_OF_USE_DECLTYPE)
int i = 123;
sfinae_test(sfinae_test_f, i);
#endif // defined(BOOST_RESULT_OF_USE_DECLTYPE)
return 0;
}

View File

@@ -143,7 +143,7 @@ void f() {
<h2><a name="result_of">Class template
result_of</a></h2> <p>The class template
<code>result_of</code> helps determine the type of a
call expression. Given an lvalue <code>f</code> of
call expression. For example, given an lvalue <code>f</code> of
type <code>F</code> and lvalues <code>t1</code>,
<code>t2</code>, ..., <code>t<em>N</em></code> of
types <code>T1</code>, <code>T2</code>, ...,
@@ -155,22 +155,24 @@ void f() {
the type <code>F</code> to be a function pointer,
function reference, member function pointer, or class
type. By default, <em>N</em> may be any value between 0 and
10. To change the upper limit, define the macro
16. To change the upper limit, define the macro
<code>BOOST_RESULT_OF_NUM_ARGS</code> to the maximum
value for <em>N</em>. Class template <code>result_of</code>
resides in the header <code>&lt;<a
href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>&gt;</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 type of the call expression, in which case
<code>result_of&lt;F(T1, T2, ...,
T<em>N</em>)&gt;::type</code> names the type
<code>decltype(boost::declval&lt;F&gt;()(boost::declval&lt;T1&gt;(),
boost::declval&lt;T2&gt;(), ...,
boost::declval&lt;T<em>N</em>&gt;()))</code>, as in the
following example.</p>
<blockquote>
<pre>#define BOOST_RESULT_OF_USE_DECLTYPE
#include &lt;boost/utility/result_of.hpp&gt;
struct functor {
<pre>struct functor {
template&lt;class T&gt;
T operator()(T x)
{
@@ -180,21 +182,29 @@ struct functor {
typedef boost::result_of&lt;
functor(int)
&gt;::type type;</pre>
&gt;::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&lt;F(T1, T2, ...,
T<em>N</em>)&gt;</code> is
T<em>N</em>)&gt;::type</code> is
<code>F::result_type</code>. When <code>F</code> does
not contain <code>result_type</code>,
<code>result_of&lt;F(T1, T2, ...,
T<em>N</em>)&gt;</code> is <code>F::result&lt;F(T1,
T<em>N</em>)&gt;::type</code> is <code>F::result&lt;F(T1,
T2, ..., T<em>N</em>)&gt;::type</code> when
<code><em>N</em> &gt; 0</code> or <code>void</code>
when <code><em>N</em> = 0</code>. Note that it is the
@@ -221,22 +231,29 @@ typedef boost::result_of&lt;
typedef boost::result_of&lt;
functor(int)
&gt;::type type;</pre>
&gt;::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&lt;&gt;</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>&lt;<a href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>&gt;</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>&lt;<a href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>&gt;</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&lt;&gt;</code> members accurately
represent the return type of
<code>operator()</code> given a call expression.</p>
<a name="BOOST_NO_RESULT_OF"></a>
<p>This implementation of <code>result_of</code>
@@ -253,7 +270,322 @@ typedef boost::result_of&lt;
<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> <a href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1454.html">proposal</a>.</p>
Contributed by Doug Gregor.</p>
<a name="result_of_guidelines">
<h3>Usage guidelines for boost::result_of</h3>
</a>
<p>The following are general suggestions about when
and how to use <code>boost::result_of</code>.</p>
<ol>
<li> If you are targeting C++11 and are not concerned
about portability to non-compliant compilers or
previous versions of the standard, then use
<code>std::result_of</code>. If <code>std::result_of</code>
meets your needs, then there's no reason to stop using
it.</li>
<li> If you are targeting C++11 but may port your code
to legacy compilers at some time in the future, then
use <code>boost::result_of</code> with
<code>decltype</code>. When <code>decltype</code> is
used <code>boost::result_of</code>
and <code>std::result_of</code> are usually
interchangeable. See the documentation on
known <a href="#result_of_cxx11_diff">differences</a>
between boost::result_of and C++11 result_of.</li>
<li> If compiler portability is required,
use <code>boost::result_of</code> with the TR1 protocol.</li>
</ol>
<p>Regardless of how you
configure <code>boost::result_of</code>, it is
important to bear in mind that the return type of a
function may change depending on its arguments, and
additionally, the return type of a member function may
change depending on the cv-qualification of the
object. <code>boost::result_of</code> must be passed
the appropriately cv-qualified types in order to
deduce the corresponding return type. For example:
<blockquote>
<pre>struct functor {
int& operator()(int);
int const& operator()(int) const;
float& operator()(float&);
float const& operator()(float const&);
};
typedef boost::result_of&lt;
functor(int)
&gt;::type type1; // type1 is int &
typedef boost::result_of&lt;
const functor(int)
&gt;::type type2; // type2 is int const &
typedef boost::result_of&lt;
functor(float&)
&gt;::type type3; // type3 is float &
typedef boost::result_of&lt;
functor(float const&)
&gt;::type type4; // type4 is float const &</pre>
</blockquote>
<a name="result_of_tr1_protocol_guidelines">
<h3>Usage guidelines for the TR1 result_of protocol</h3>
</a>
<p>On compliant C++11
compilers, <code>boost::result_of</code> can
use <code>decltype</code> to deduce the type of any
call expression, including calls to function
objects. However, on pre-C++11 compilers or on
compilers without adequate decltype support,
additional scaffolding is needed from function
objects as described above. The following are
suggestions about how to use the TR1 protocol.</p>
<ul>
<li>When the return type does not depend on the
argument types or the cv-qualification of the
function object, simply
define <code>result_type</code>. There is no need
to use the <code>result</code> template unless the
return type varies.</li>
<li>Use the protocol specified type when defining
function prototypes. This can help ensure the
actual return type does not get out of sync with
the protocol specification. For example:
<blockquote>
<pre>struct functor {
typedef int result_type;
result_type operator()(int);
};</pre>
</blockquote> </li>
<li>Always specify the <code>result</code>
specialization near the corresponding
<code>operator()</code> overload. This can make it
easier to keep the specializations in sync with the
overloads. For example:
<blockquote>
<pre>struct functor {
template&lt;class&gt; struct result;
template&lt;class F&gt;
struct result&lt;F(int)&gt; {
typedef int& type;
};
result&lt;functor(int)&gt;::type operator()(int);
template&lt;class F&gt;
struct result&lt;const F(int)&gt; {
typedef int const& type;
};
result&lt;const functor(int)&gt;::type operator()(int) const;
};</pre>
</blockquote> </li>
<li>Use type transformations to simplify
the <code>result</code> template specialization. For
example, the following uses
<a href="../type_traits/doc/html/index.html">Boost.TypeTraits</a>
to specialize the <code>result</code> template for
a single <code>operator()</code> that can be called on
both a const and non-const function object with
either an lvalue or rvalue argument.
<blockquote>
<pre>struct functor {
template&lt;class&gt; struct result;
template&lt;class F, class T&gt;
struct result&lt;F(T)&gt;
: boost::remove_cv&lt;
typename boost::remove_reference&lt;T&gt;::type
&gt;
{};
template&lt;class T&gt;
T operator()(T const&amp; x) const;
};</pre>
</blockquote></li>
</ul>
<a name="result_of_tr1_diff">
<h3>Known differences between boost::result_of and TR1 result_of</h3>
</a>
When using <code>decltype</code>, <code>boost::result_of</code>
ignores the TR1 protocol and instead deduces the
return type of function objects directly
via <code>decltype</code>. In most situations, users
will not notice a difference, so long as they use the
protocol correctly. The following are situations in
which the type deduced
by <code>boost::result_of</code> is known to differ depending on
whether <code>decltype</code> or the TR1 protocol is
used.
<ul>
<li> TR1 protocol misusage
<p>When using the TR1
protocol, <code>boost::result_of</code> cannot
detect whether the actual type of a call to a
function object is the same as the type specified
by the protocol, which allows for the possibility
of inadvertent mismatches between the specified
type and the actual type. When
using <code>decltype</code>, these subtle bugs
may result in compilation errors. For example:</p>
<blockquote>
<pre>struct functor {
typedef short result_type;
int operator()(short);
};
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
boost::is_same&lt;boost::result_of&lt;functor(short)&gt;::type, int&gt;::value
));
#else
BOOST_STATIC_ASSERT((
boost::is_same&lt;boost::result_of&lt;functor(short)&gt;::type, short&gt;::value
));
#endif</pre>
</blockquote>
<p>Note that the user can
force <code>boost::result_of</code> to use the TR1
protocol even on platforms that
support <code>decltype</code> by
defining <code>BOOST_RESULT_OF_USE_TR1</code>.</p></li>
<li> Nullary function objects
<p>When using the TR1 protocol, <code>boost::result_of</code>
cannot always deduce the type of calls to
nullary function objects, in which case the
type defaults to void. When using <code>decltype</code>,
<code>boost::result_of</code> always gives the actual type of the
call expression. For example:</p>
<blockquote>
<pre>struct functor {
template&lt;class&gt; struct result {
typedef int type;
};
int operator()();
};
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
boost::is_same&lt;boost::result_of&lt;functor()&gt;::type, int&gt;::value
));
#else
BOOST_STATIC_ASSERT((
boost::is_same&lt;boost::result_of&lt;functor()&gt;::type, void&gt;::value
));
#endif</pre>
</blockquote>
<p>Note that there are some workarounds for the
nullary function problem. So long as the return
type does not vary,
<code>result_type</code> can always be used to
specify the return type regardless of arity. If the
return type does vary, then the user can
specialize <code>boost::result_of</code> itself for
nullary calls.</p></li>
<li> Non-class prvalues and cv-qualification
<p>When using the TR1
protocol, <code>boost::result_of</code> will
report the cv-qualified type specified
by <code>result_type</code> or
the <code>result</code> template regardless of
the actual cv-qualification of the call
expression. When using
<code>decltype</code>, <code>boost::result_of</code>
will report the actual type of the call expression,
which is not cv-qualified when the expression is a
non-class prvalue. For example:</p>
<blockquote>
<pre>struct functor {
template&lt;class&gt; struct result;
template&lt;class F, class T&gt; struct result&lt;F(const T)&gt; {
typedef const T type;
};
const short operator()(const short);
int const & operator()(int const &);
};
// Non-prvalue call expressions work the same with or without decltype.
BOOST_STATIC_ASSERT((
boost::is_same&lt;
boost::result_of&lt;functor(int const &)&gt;::type,
int const &
::value
));
// Non-class prvalue call expressions are not actually cv-qualified,
// but only the decltype-based result_of reports this accurately.
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
BOOST_STATIC_ASSERT((
boost::is_same&lt;
boost::result_of&lt;functor(const short)&gt;::type,
short
::value
));
#else
BOOST_STATIC_ASSERT((
boost::is_same&lt;
boost::result_of&lt;functor(const short)&gt;::type,
const short
::value
));
#endif</pre>
</blockquote></li>
</ul>
<a name="result_of_cxx11_diff">
<h3>Known differences between boost::result_of and C++11 result_of</h3>
</a>
<p>When using <code>decltype</code>, <code>boost::result_of</code>
implements most of the C++11 result_of
specification. One known exception is that
<code>boost::result_of</code> does not implement the
requirements regarding pointers to member data.</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 <a href="base_from_member.html">separate documentation</a>.</p>