mirror of
https://github.com/boostorg/utility.git
synced 2025-05-11 13:24:02 +00:00
result_of: merge [80445], [80452], [80535], [80550], [80605], [80608] from trunk
[SVN r80621]
This commit is contained in:
parent
1920623a4f
commit
7d8353f46a
@ -58,17 +58,79 @@ struct result_of<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
|
||||||
|
|
||||||
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||||
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
|
||||||
struct cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
|
class is_callable<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))> {
|
||||||
|
typedef char (&pass)[1];
|
||||||
|
typedef char (&fail)[2];
|
||||||
|
|
||||||
|
template<typename G BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||||
|
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename S)>
|
||||||
|
struct sub {};
|
||||||
|
template<typename S>
|
||||||
|
struct stub {};
|
||||||
|
|
||||||
|
template<typename G BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||||
|
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename S)>
|
||||||
|
static pass test(sub<G BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||||
|
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),S)>
|
||||||
|
, stub<
|
||||||
|
decltype(
|
||||||
|
boost::declval<G>()(
|
||||||
|
BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_ITERATION(), boost::declval<S, >() BOOST_PP_INTERCEPT)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
>* x = 0);
|
||||||
|
static fail test(...);
|
||||||
|
|
||||||
|
public:
|
||||||
|
const static bool value = sizeof(pass) == sizeof(test(sub<F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
|
||||||
|
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)
|
||||||
|
>()));
|
||||||
|
typedef typename boost::mpl::bool_<value>::type type;
|
||||||
|
};
|
||||||
|
|
||||||
|
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)), true>
|
||||||
|
: lazy_enable_if<
|
||||||
|
is_callable<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T))>
|
||||||
|
, cpp0x_result_of_impl<F(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), false>
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
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)), false>
|
||||||
{
|
{
|
||||||
typedef decltype(
|
typedef decltype(
|
||||||
boost::declval<F>()(
|
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;
|
) type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#else // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
|
||||||
|
|
||||||
|
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)),
|
||||||
|
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_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
#else // defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
#else // defined(BOOST_RESULT_OF_USE_DECLTYPE)
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <boost/type_traits/is_member_function_pointer.hpp>
|
#include <boost/type_traits/is_member_function_pointer.hpp>
|
||||||
#include <boost/type_traits/remove_cv.hpp>
|
#include <boost/type_traits/remove_cv.hpp>
|
||||||
#include <boost/utility/declval.hpp>
|
#include <boost/utility/declval.hpp>
|
||||||
|
#include <boost/utility/enable_if.hpp>
|
||||||
|
|
||||||
#ifndef BOOST_RESULT_OF_NUM_ARGS
|
#ifndef BOOST_RESULT_OF_NUM_ARGS
|
||||||
# define BOOST_RESULT_OF_NUM_ARGS 16
|
# define BOOST_RESULT_OF_NUM_ARGS 16
|
||||||
@ -59,7 +60,22 @@ namespace detail {
|
|||||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
|
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
|
||||||
|
|
||||||
template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
|
template<typename F, typename FArgs, bool HasResultType> struct tr1_result_of_impl;
|
||||||
template<typename F> struct cpp0x_result_of_impl;
|
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
|
||||||
|
|
||||||
|
template<typename F> class is_callable;
|
||||||
|
template<typename F, bool TestCallability = true> struct cpp0x_result_of_impl;
|
||||||
|
|
||||||
|
#else // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct result_of_always_void
|
||||||
|
{
|
||||||
|
typedef void type;
|
||||||
|
};
|
||||||
|
template<typename F, typename Enable = void> struct cpp0x_result_of_impl {};
|
||||||
|
|
||||||
|
#endif // BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1700))
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
struct result_of_void_impl
|
struct result_of_void_impl
|
||||||
|
@ -129,6 +129,27 @@ struct no_result_type_or_result_template
|
|||||||
#endif
|
#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 {};
|
struct X {};
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
@ -268,5 +289,10 @@ int main()
|
|||||||
#endif
|
#endif
|
||||||
#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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
331
utility.htm
331
utility.htm
@ -143,7 +143,7 @@ void f() {
|
|||||||
<h2><a name="result_of">Class template
|
<h2><a name="result_of">Class template
|
||||||
result_of</a></h2> <p>The class template
|
result_of</a></h2> <p>The class template
|
||||||
<code>result_of</code> helps determine the type of a
|
<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>,
|
type <code>F</code> and lvalues <code>t1</code>,
|
||||||
<code>t2</code>, ..., <code>t<em>N</em></code> of
|
<code>t2</code>, ..., <code>t<em>N</em></code> of
|
||||||
types <code>T1</code>, <code>T2</code>, ...,
|
types <code>T1</code>, <code>T2</code>, ...,
|
||||||
@ -163,12 +163,16 @@ void f() {
|
|||||||
|
|
||||||
<p>If your compiler's support for <code>decltype</code> is
|
<p>If your compiler's support for <code>decltype</code> is
|
||||||
adequate, <code>result_of</code> automatically uses it to
|
adequate, <code>result_of</code> automatically uses it to
|
||||||
deduce the result type of your callable object.</p>
|
deduce the type of the call expression, in which case
|
||||||
|
<code>result_of<F(T1, T2, ...,
|
||||||
|
T<em>N</em>)>::type</code> names the type
|
||||||
|
<code>decltype(boost::declval<F>()(boost::declval<T1>(),
|
||||||
|
boost::declval<T2>(), ...,
|
||||||
|
boost::declval<T<em>N</em>>())), as in the
|
||||||
|
following example.</p>
|
||||||
|
|
||||||
<blockquote>
|
<blockquote>
|
||||||
<pre>#include <boost/utility/result_of.hpp>
|
<pre>struct functor {
|
||||||
|
|
||||||
struct functor {
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T operator()(T x)
|
T operator()(T x)
|
||||||
{
|
{
|
||||||
@ -249,7 +253,7 @@ typedef boost::result_of<
|
|||||||
<code>result_type</code> and
|
<code>result_type</code> and
|
||||||
<code>result<></code> members accurately
|
<code>result<></code> members accurately
|
||||||
represent the return type of
|
represent the return type of
|
||||||
<code>operator()</code>.</p>
|
<code>operator()</code> given a call expression.</p>
|
||||||
|
|
||||||
<a name="BOOST_NO_RESULT_OF"></a>
|
<a name="BOOST_NO_RESULT_OF"></a>
|
||||||
<p>This implementation of <code>result_of</code>
|
<p>This implementation of <code>result_of</code>
|
||||||
@ -266,6 +270,321 @@ typedef boost::result_of<
|
|||||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">N1836</a>,
|
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">N1836</a>,
|
||||||
or, for motivation and design rationale,
|
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>
|
the <code>result_of</code> <a href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1454.html">proposal</a>.</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<
|
||||||
|
functor(int)
|
||||||
|
>::type type1; // type1 is int &
|
||||||
|
|
||||||
|
typedef boost::result_of<
|
||||||
|
const functor(int)
|
||||||
|
>::type type2; // type2 is int const &
|
||||||
|
|
||||||
|
typedef boost::result_of<
|
||||||
|
functor(float&)
|
||||||
|
>::type type3; // type3 is float &
|
||||||
|
|
||||||
|
typedef boost::result_of<
|
||||||
|
functor(float const&)
|
||||||
|
>::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<class> struct result;
|
||||||
|
|
||||||
|
template<class F>
|
||||||
|
struct result<F(int)> {
|
||||||
|
typedef int& type;
|
||||||
|
};
|
||||||
|
result<functor(int)>::type operator()(int);
|
||||||
|
|
||||||
|
template<class F>
|
||||||
|
struct result<const F(int)> {
|
||||||
|
typedef int const& type;
|
||||||
|
};
|
||||||
|
result<const functor(int)>::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<class> struct result;
|
||||||
|
|
||||||
|
template<class F, class T>
|
||||||
|
struct result<F(T)>
|
||||||
|
: boost::remove_cv<
|
||||||
|
typename boost::remove_reference<T>::type
|
||||||
|
>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T operator()(T const& 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<boost::result_of<functor(short)>::type, int>::value
|
||||||
|
));
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_same<boost::result_of<functor(short)>::type, short>::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<class> struct result {
|
||||||
|
typedef int type;
|
||||||
|
};
|
||||||
|
int operator()();
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef BOOST_RESULT_OF_USE_DECLTYPE
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_same<boost::result_of<functor()>::type, int>::value
|
||||||
|
));
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_same<boost::result_of<functor()>::type, void>::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<class> struct result;
|
||||||
|
template<class F, class T> struct result<F(const T)> {
|
||||||
|
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<
|
||||||
|
boost::result_of<functor(int const &)>::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<
|
||||||
|
boost::result_of<functor(const short)>::type,
|
||||||
|
short
|
||||||
|
::value
|
||||||
|
));
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
BOOST_STATIC_ASSERT((
|
||||||
|
boost::is_same<
|
||||||
|
boost::result_of<functor(const short)>::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>
|
<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>
|
<h2>Class templates for the Base-from-Member Idiom</h2>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user