Index: utility.htm
===================================================================
--- utility.htm (revision 80454)
+++ utility.htm (working copy)
@@ -260,6 +260,70 @@
boost/utility/result_of.hpp
will
define the macro BOOST_NO_RESULT_OF
.
It is important to understand that result_of
template (whether decltype
-based or not) should be instantiated with the exact types of the
+ function object and arguments used at the call site. This includes the correct const
/volatile
and reference qualification of the arguments.
+ Failing to do so may affect the deduced result type and create subtle errors. Following are the typical use case examples:
++ +typedef boost::result_of< functor(int) >::type type1; // the argument is rvalue +functor f; +type1 r1 = f(10); + +typedef boost::result_of< const functor(int) >::type type2; // the function object is const +const functor cf; +type2 r2 = cf(10); + +typedef boost::result_of< functor(int&) >::type type3; // the argument is lvalue +int a = 10; +type3 r3 = f(a); + +typedef boost::result_of< functor(int const&) >::type type4; // the argument is const lvalue +const int ca = 10; +type4 r4 = f(ca);+
When code is targeted to compliant C++11 compilers and portability is not an issue, one can use std::result_of
+ or decltype
-based boost::result_of
interchangeably. No additional scaffolding is needed from function objects,
+ the compiler will be able to deduce the result type from the operator()
itself.
If compatibility with C++03 is required, one has to always use boost::result_of
which will fall back to TR1 protocol
+ when decltype
is not available. This will also require support from function objects as follows.
operator()
argument types, simply define it as the result_type
type within the function object.result
template specializations.The latter case is the most complicated. The result
template should be specialized to account for every valid calling signature the function object supports.
+ If the operator()
accepts arguments by (possibly const
) reference and/or the operator itself is const
+ qualified, the result
specialization must support it as well. Type traits
+ and more generic specializations may help to reduce the number of result
specializations. For example:
++ +struct functor { + template<class> struct result; + + // Use template parameter F to match the function object. This will allow result deduction for both const and non-const functor. + template<class F, class T> + struct result<F(T)> { + // When argument type is matched like above, remember that the type may be a (const-qualified) reference. + // Use type traits to transform the argument type. + typedef typename remove_cv<typename remove_reference<T>::type>::type argument_type; + typedef argument_type type; + }; + + // The operator can be called on both const and non-const functor. The argument can be lvalue or rvalue. + template<class T> + T operator()(T const& x) const + { + return x; + } +};+
This way result_of
users will be able to specify argument types exactly according to the function object call expression.
For additional information
about result_of
, see the C++ Library
Technical Report,