From a4e332c4c096d42010fb55dce7db5085c817dae7 Mon Sep 17 00:00:00 2001
From: Daniel Walker The class template
If your compiler's support for Class template
result_of
result_of
helps determine the type of a
- call expression. Given an lvalue f
of
+ call expression. For example, given an lvalue f
of
type F
and lvalues t1
,
t2
, ..., tN
of
types T1
, T2
, ...,
@@ -163,12 +163,16 @@ void f() {
decltype
is
adequate, result_of
automatically uses it to
- deduce the result type of your callable object.result_of<F(T1, T2, ...,
+ TN)>::type
names the type
+ decltype(boost::declval<F>()(boost::declval<T1>(),
+ boost::declval<T2>(), ...,
+ boost::declval<TN>())), as in the
+ following example.
-#include <boost/utility/result_of.hpp> - -struct functor { +struct functor { template<class T> T operator()(T x) { @@ -249,7 +253,7 @@ typedef boost::result_of<result_type
andresult<>
members accurately represent the return type of -operator()
. +operator()
given a call expression.This implementation of
+ + +result_of
@@ -266,6 +270,321 @@ typedef boost::result_of< N1836, or, for motivation and design rationale, theresult_of
proposal.Usage guidelines for boost::result_of
+ + +The following are general suggestions about when + and how to use
+ +boost::result_of
.+
+ +- If you are targeting C++11 and are not concerned + about portability to non-compliant compilers or + previous versions of the standard, then use +
+ +std::result_of
. Ifstd::result_of
+ meets your needs, then there's no reason to stop using + it.- If you are targeting C++11 but may port your code + to legacy compilers at some time in the future, then + use
+ +boost::result_of
with +decltype
. Whendecltype
is + usedboost::result_of
+ andstd::result_of
are usually + interchangeable. See the documentation on + known differences + between boost::result_of and C++11 result_of.- If compiler portability is required, + use
+boost::result_of
with the TR1 protocol.Regardless of how you + configure
boost::result_of
, 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.boost::result_of
must be passed + the appropriately cv-qualified types in order to + deduce the corresponding return type. For example: + +++ + +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 &+Usage guidelines for the TR1 result_of protocol
+ + +On compliant C++11 + compilers,
+ +boost::result_of
can + usedecltype
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.+
+ + +- When the return type does not depend on the + argument types or the cv-qualification of the + function object, simply + define
+ +result_type
. There is no need + to use theresult
template unless the + return type varies.- 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: + +
+ ++struct functor { + typedef int result_type; + result_type operator()(int); +};+- Always specify the
+ +result
+ specialization near the corresponding +operator()
overload. This can make it + easier to keep the specializations in sync with the + overloads. For example: + ++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; +};+- Use type transformations to simplify + the
+result
template specialization. For + example, the following uses + Boost.TypeTraits + to specialize theresult
template for + a singleoperator()
that can be called on + both a const and non-const function object with + either an lvalue or rvalue argument. + ++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; +};+Known differences between boost::result_of and TR1 result_of
+ + + When usingdecltype
,boost::result_of
+ ignores the TR1 protocol and instead deduces the + return type of function objects directly + viadecltype
. 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 + byboost::result_of
is known to differ depending on + whetherdecltype
or the TR1 protocol is + used. + ++
+ + +- TR1 protocol misusage + +
+ +When using the TR1 + protocol,
+ +boost::result_of
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 + usingdecltype
, these subtle bugs + may result in compilation errors. For example:++ +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+Note that the user can + force
boost::result_of
to use the TR1 + protocol even on platforms that + supportdecltype
by + definingBOOST_RESULT_OF_USE_TR1
.- Nullary function objects + +
+ +When using the TR1 protocol,
+ +boost::result_of
+ cannot always deduce the type of calls to + nullary function objects, in which case the + type defaults to void. When usingdecltype
, +boost::result_of
always gives the actual type of the + call expression. For example:++ +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+Note that there are some workarounds for the + nullary function problem. So long as the return + type does not vary, +
result_type
can always be used to + specify the return type regardless of arity. If the + return type does vary, then the user can + specializeboost::result_of
itself for + nullary calls.- Non-class prvalues and cv-qualification + +
+When using the TR1 + protocol,
+ +boost::result_of
will + report the cv-qualified type specified + byresult_type
or + theresult
template regardless of + the actual cv-qualification of the call + expression. When using +decltype
,boost::result_of
+ will report the actual type of the call expression, + which is not cv-qualified when the expression is a + non-class prvalue. For example:+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+Known differences between boost::result_of and C++11 result_of
+ + +When using
+decltype
,boost::result_of
+ implements most of the C++11 result_of + specification. One known exception is that +boost::result_of
does not implement the + requirements regarding pointers to member data.Created by Doug Gregor. Contributions from Daniel Walker, Eric Niebler, Michel Morin and others
Class templates for the Base-from-Member Idiom