mirror of
https://github.com/boostorg/functional.git
synced 2026-01-23 05:32:11 +00:00
172 lines
6.3 KiB
HTML
172 lines
6.3 KiB
HTML
<html>
|
|
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|
<title>Boost Function Object Adapter Library</title>
|
|
</head>
|
|
|
|
<body bgcolor="#FFFFFF" text="#000000">
|
|
|
|
<table border="1" bgcolor="#007F7F" cellpadding="2">
|
|
<tr>
|
|
<td bgcolor="#FFFFFF"><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" WIDTH="277" HEIGHT="86"></td>
|
|
<td><a href="../../index.htm"><font face="Arial" color="#FFFFFF"><big>Home </big></font></a></td>
|
|
<td><a href="../libraries.htm"><font face="Arial" color="#FFFFFF"><big>Libraries </big></font></a></td>
|
|
<td><a href="../../people/people.htm"><font face="Arial" color="#FFFFFF"><big>People </big></font></a></td>
|
|
<td><a href="../../more/faq.htm"><font face="Arial" color="#FFFFFF"><big>FAQ </big></font></a></td>
|
|
<td><a href="../../more/index.htm"><font face="Arial" color="#FFFFFF"><big>More </big></font></a></td>
|
|
</tr>
|
|
</table>
|
|
|
|
<h1>Member Function Adapters</h1>
|
|
|
|
<p>The header <nobr><a
|
|
href="../../boost/functional.hpp">functional.hpp</a></nobr> includes
|
|
improved versions of the full range of member function adapters from
|
|
the the C++ Standard Library <nobr>(§ 20.3.8):</nobr></p>
|
|
|
|
<ul>
|
|
<li><tt>mem_fun_t</tt></li>
|
|
<li><tt>mem_fun1_t</tt></li>
|
|
<li><tt>const_mem_fun_t</tt></li>
|
|
<li><tt>const_mem_fun1_t</tt></li>
|
|
<li><tt>mem_fun_ref_t</tt></li>
|
|
<li><tt>mem_fun1_ref_t</tt></li>
|
|
<li><tt>const_mem_fun_ref_t</tt></li>
|
|
<li><tt>const_mem_fun1_ref_t</tt></li>
|
|
</ul>
|
|
|
|
<p>as well as the corresponding overloaded helper functions<p>
|
|
<ul>
|
|
<li><tt>mem_fun</tt></li>
|
|
<li><tt>mem_fun_ref</tt></li>
|
|
</ul>
|
|
|
|
<p>The following changes have been made to the adapters as specified
|
|
in the Standard:</p>
|
|
|
|
<ul>
|
|
<li>The <tt><nobr>first_argument_type</nobr></tt> typedef has been
|
|
corrected for the <nobr><tt>const_</tt></nobr> family of member
|
|
function adapters (see <a href="#firstarg">below</a>).</li>
|
|
|
|
<li>The argument passed to <tt><nobr>mem_fun1_t</nobr></tt> and its
|
|
variants is passed using the
|
|
<tt><nobr>call_traits::param_type</nobr></tt> for the member
|
|
function's argument type.
|
|
</ul>
|
|
|
|
<h3 id="firstarg">first_argument_type</h3>
|
|
|
|
<p>The standard specifies <tt><nobr>const_mem_fun1_t</nobr></tt>, for example, like this:
|
|
|
|
<blockquote><pre>
|
|
template <class S, class T, class A> class const_mem_fun1_t
|
|
: public binary_function<<strong>T*</strong>, A, S> {
|
|
public:
|
|
explicit const_mem_fun1_t(S (T::*p)(A) const);
|
|
S operator()(<strong>const T*</strong> p, A x) const;
|
|
};
|
|
</pre></blockquote>
|
|
|
|
<p>Note that the first argument to
|
|
<tt><nobr>binary_function</nobr></tt> is <tt><nobr>T*</nobr></tt>
|
|
despite the fact that the first argument to <tt><nobr>operator()</nobr></tt> is
|
|
actually of type <tt><nobr><em>const</em> T*</nobr></tt>.
|
|
|
|
<p>Does this matter? Well, consider what happens when we write
|
|
|
|
<blockquote><pre>
|
|
struct Foo { void bar(int) const; };
|
|
const Foo *cp = new Foo;
|
|
std::bind1st(std::mem_fun(&Foo::bar), cp);
|
|
</pre></blockquote>
|
|
|
|
<p>We have created a <tt><nobr>const_mem_fun1_t</nobr></tt> object
|
|
which will effectively contain the following
|
|
|
|
<blockquote><pre>
|
|
typedef Foo* first_argument_type;
|
|
</pre></blockquote>
|
|
|
|
<p>The <tt><nobr>bind1st</nobr></tt> will then create a
|
|
<tt><nobr>binder1st</nobr></tt> object that will use this
|
|
<tt><nobr>typedef</nobr></tt> as the type of a member which will be
|
|
initialised with <tt><nobr>cp</nobr></tt>. In other words, we will
|
|
need to initialise a <tt><nobr>Foo*</nobr></tt> member with a
|
|
<tt><nobr>const Foo*</nobr></tt> pointer! Clearly this is not
|
|
possible, so to implement this your Standard Library vendor will have
|
|
had to cast away the constness of <tt><nobr>cp</nobr></tt>, probably
|
|
within the body of <tt><nobr>bind1st</nobr></tt>.
|
|
|
|
<p>This hack will not suffice with the improved <a
|
|
href="binders.html">binders</a> in this library, so we have had to
|
|
provide corrected versions of the member function adapters as well.
|
|
|
|
|
|
<h3 id="args">Argument Types</h3>
|
|
|
|
<p>The standard defines <nobr><tt>mem_fun1_t</tt></nobr>, for example, like this
|
|
<nobr>(§20.3.8 ¶2):</nobr>
|
|
|
|
<blockquote><pre>
|
|
template <class S, class T, class A> class mem_fun1_t
|
|
: public binary_function<T*, A, S> {
|
|
public:
|
|
explicit mem_fun1_t(S (T::*p)(<strong>A</strong>));
|
|
S operator()(T* p, <strong>A</strong> x) const;
|
|
};
|
|
</pre></blockquote>
|
|
|
|
<p>Note that the second argument to <nobr><tt>operator()</tt></nobr> is
|
|
exactly the same type as the argument to the member function. If this
|
|
is a value type, the argument will be passed by value and copied twice.
|
|
|
|
<p>However, if we were to try and eliminate this inefficiency by
|
|
instead declaring the argument as <nobr><tt>const A&</tt></nobr>, then
|
|
if A were a reference type, we would have a reference to a reference,
|
|
which is currently illegal (but see <a
|
|
href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#106">C++
|
|
core language issue number 106)</a>
|
|
|
|
<p>So the way in which we want to declare the second argument for
|
|
<nobr><tt>operator()</tt></nobr> depends on whether or not the member
|
|
function's argument is a reference. If it is a reference, we want to
|
|
declare it simply as <nobr><tt>A</tt></nobr>; if it is a value we want
|
|
to declare it as <nobr><tt>const A&</tt></nobr>.
|
|
|
|
<p>The Boost <nobr><a
|
|
href="../utility/call_traits.htm">call_traits</a></nobr> class
|
|
template contains a <tt><nobr>param_type</nobr></tt> typedef, which
|
|
uses partial specialisation to make precisely this decision. By
|
|
declaring the <nobr><tt>operator()</tt></nobr> as
|
|
|
|
<blockquote><pre>
|
|
S operator()(T* p, typename call_traits<A>::param_type x) const
|
|
</pre></blockquote>
|
|
|
|
<p>we achieve the desired result - we improve efficiency without
|
|
generating references to references.</p>
|
|
|
|
<h3>Limitations</h3>
|
|
|
|
<p>The call traits template used to realise some improvements relies
|
|
on partial specialisation, so these improvements are only available on
|
|
compilers that support that feature. With other compilers, the
|
|
argument passed to the member function (in the
|
|
<nobr><tt>mem_fun1_t</tt></nobr> family) will always be passed by
|
|
reference, thus generating the possibility of references to references.
|
|
|
|
<hr>
|
|
|
|
<p>Copyright © 2000 Cadenza New Zealand Ltd. Permission to copy,
|
|
use, modify, sell and distribute this document is granted provided
|
|
this copyright notice appears in all copies. This document is provided
|
|
"as is" without express or implied warranty, and with no claim as to
|
|
its suitability for any purpose.</p>
|
|
|
|
<p>Revised 28 June 2000</p>
|
|
|
|
</body>
|
|
</html>
|