Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r80535 - trunk/libs/utility
From: daniel.j.walker_at_[hidden]
Date: 2012-09-15 20:39:42


Author: djwalker
Date: 2012-09-15 20:39:41 EDT (Sat, 15 Sep 2012)
New Revision: 80535
URL: http://svn.boost.org/trac/boost/changeset/80535

Log:
updated docs to include guidelines, changes and various suggestions from Andrey Semashev, JeffLee Hellrung and others
Text files modified:
   trunk/libs/utility/utility.htm | 331 +++++++++++++++++++++++++++++++++++++++
   1 files changed, 325 insertions(+), 6 deletions(-)

Modified: trunk/libs/utility/utility.htm
==============================================================================
--- trunk/libs/utility/utility.htm (original)
+++ trunk/libs/utility/utility.htm 2012-09-15 20:39:41 EDT (Sat, 15 Sep 2012)
@@ -143,7 +143,7 @@
                 <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>, ...,
@@ -163,12 +163,16 @@
 
                 <p>If your compiler's support for <code>decltype</code> is
                 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&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;())), as in the
+ following example.</p>
 
                 <blockquote>
- <pre>#include &lt;boost/utility/result_of.hpp&gt;
-
-struct functor {
+ <pre>struct functor {
     template&lt;class T&gt;
     T operator()(T x)
     {
@@ -249,7 +253,7 @@
                 <code>result_type</code> and
                 <code>result&lt;&gt;</code> members accurately
                 represent the return type of
- <code>operator()</code>.</p>
+ <code>operator()</code> given a call expression.</p>
 
                 <a name="BOOST_NO_RESULT_OF"></a>
                 <p>This implementation of <code>result_of</code>
@@ -266,6 +270,321 @@
                 <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> proposal.</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 differences
+ 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
+ Boost.TypeTraits
+ 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>


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk