mirror of
https://github.com/boostorg/utility.git
synced 2025-05-09 15:04:00 +00:00
updated docs to include guidelines, changes and various suggestions from Andrey Semashev, JeffLee Hellrung and others
[SVN r80535]
This commit is contained in:
parent
e9bbb50eb4
commit
a4e332c4c0
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