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.

+

Usage guidelines

+ +

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.

+ + +

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,