1
0
forked from boostorg/bind

Initial commit

[SVN r11022]
This commit is contained in:
Peter Dimov
2001-09-04 17:16:30 +00:00
parent b87bb90661
commit 90433660f9
11 changed files with 3900 additions and 0 deletions

721
bind.html Normal file
View File

@@ -0,0 +1,721 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Boost: bind.hpp documentation</title>
</head>
<body bgcolor="White">
<table border="0" width="100%">
<tr>
<td align="center">
<table border="0" width="90%">
<tr>
<td width="277">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" WIDTH="277" HEIGHT="86">
</td>
<td align="center">
<table border="0">
<tr><td nowrap><h1>bind.hpp</h1></td></tr>
<tr><td align="right" nowrap><small>&nbsp;1.01.0001 (2001-09-02)</small></td></tr>
</table>
</td>
</tr>
<tr>
<td height="64">&nbsp;</td>
</tr>
</table>
<table border="0" width="90%">
<tr>
<td>
<h2>Files</h2>
<ul>
<li><a href="../../boost/bind.hpp">bind.hpp</a> (implementation)</li>
<li><a href="bind_test.cpp">bind_test.cpp</a> (monolithic test)</li>
<li><a href="bind_test_1.cpp">bind_test_1.cpp</a> (test with function pointers)</li>
<li><a href="bind_test_2.cpp">bind_test_2.cpp</a> (test with function objects)</li>
<li><a href="bind_test_3.cpp">bind_test_3.cpp</a> (test with member function pointers)</li>
<li><a href="bind_test_4.cpp">bind_test_4.cpp</a> (test with a visitor)</li>
<li><a href="bind_as_compose.cpp">bind_as_compose.cpp</a> (function composition example)</li>
</ul>
<h2>Purpose</h2>
<p>
<b>boost::bind</b> is a generalization of the standard functions
<b>std::bind1st</b> and <b>std::bind2nd</b>. It supports arbitrary function
objects, functions, function pointers, and member function pointers, and is able
to bind any argument to a specific value or route input arguments into arbitrary
positions. <b>bind</b> does not place any requirements on the function object;
in particular, it does not need the <b>result_type</b>,
<b>first_argument_type</b> and <b>second_argument_type</b> standard typedefs.
</p>
<h3>Using bind with functions and function pointers</h3>
<p>
Given these definitions:
</p>
<pre>
int f(int a, int b)
{
return a + b;
}
int g(int a, int b, int c)
{
return a + b + c;
}
</pre>
<p>
<tt>bind(f, 1, 2)</tt> will produce a "nullary" function object that
takes no arguments and returns <tt>f(1, 2)</tt>. Similarly,
<tt>bind(g, 1, 2, 3)()</tt> is equivalent to <tt>g(1, 2, 3)</tt>.
</p>
<p>
It is possible to selectively bind only some of the arguments.
<tt>bind(f, _1, 5)(x)</tt> is equivalent to <tt>f(x, 5)</tt>; here
<b>_1</b> is a placeholder argument that means "substitute with the first
input argument."
<p>
For comparison, here is the same operation expressed with the standard
library primitives:
</p>
<pre>
std::bind1st(std::ptr_fun(f), 5)(x);
</pre>
<p>
<b>bind</b> covers the functionality of <b>std::bind2nd</b> as well:
</p>
<pre>
std::bind2nd(std::ptr_fun(f), 5)(x); // f(5, x)
bind(f, 5, _1)(x); // f(5, x)
</pre>
<p>
<b>bind</b> can handle functions with more than two arguments, and its
argument substitution mechanism is more general:
</p>
<pre>
bind(f, _2, _1)(x, y); // f(y, x)
bind(g, _1, 9, _1)(x); // g(x, 9, x)
bind(g, _3, _3, _3)(x, y, z); // g(z, z, z)
bind(g, _1, _1, _1)(x, y, z); // g(x, x, x)
</pre>
<p>
The arguments that <b>bind</b> takes are copied and held internally by
the returned function object. For example, in the following code:
</p>
<pre>
int i = 5;
bind(f, i, _1);
</pre>
<p>
a copy of the value of <b>i</b> is stored into the function object.
<a href="ref.html">boost::ref</a> and <a href="ref.html">boost::cref</a>
can be used to make the function object store a reference to an object,
rather than a copy:
</p>
<pre>
int i = 5;
bind(f, ref(i), _1);
</pre>
<h3>Using bind with function objects</h3>
<p>
Any function object can be passed as a first argument to <b>bind</b>, but the
syntax is a bit different. The return type of the generated function object's
<b>operator()</b> has to be specified explicitly (without a <b>typeof</b>
operator the return type cannot be inferred in the general case):
</p>
<pre>
struct F
{
int operator()(int a, int b) { return a - b; }
bool operator()(long a, long b) { return a == b; }
};
F f;
int x = 104;
bind&lt;int&gt;(f, _1, _1)(x); // f(x, x), i.e. zero
</pre>
<p>
[Note: when, hopefully,
<a href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#226">
function template default arguments</a> become part of C++,
<b>bind</b> will no longer require the explicit specification of the return type
when the function object defines <b>result_type</b>.]
</p>
<h3>Using bind with member function pointers</h3>
<p>
Pointers to member functions are not function objects, because they do not
support <tt>operator()</tt>. For convenience, <b>bind</b> accepts member function
pointers as its first argument, and the behavior is as if
<a href="mem_fn.html">boost::mem_fn</a> has been used to convert the member
function pointer into a function object. In other words, the expression
</p>
<pre>
bind(&amp;X::f, <i>args</i>)
</pre>
<p>
is equivalent to
</p>
<pre>
bind&lt;R&gt;(<a href="mem_fn.html">mem_fn</a>(&amp;X::f), <i>args</i>)
</pre>
<p>
where <b>R</b> is the return type of <b>X::f</b>.
</p>
<p>
[Note: <b>mem_fn</b> creates
function objects that are able to accept a pointer, a reference, or a smart
pointer to an object as its first argument; for additional information, see
the <b>mem_fn</b> <a href="mem_fn.html">documentation</a>.]
</p>
<p>
Example:
</p>
<pre>
struct X
{
bool f(int a);
};
X x;
shared_ptr&lt;X&gt; p(new X);
int i = 5;
bind(&amp;X::f, ref(x), _1)(i); // x.f(i)
bind(&amp;X::f, &x, _1)(i); // (&x)->f(i)
bind(&amp;X::f, x, _1)(i); // (<i>internal copy of x</i>).f(i)
bind(&amp;X::f, p, _1)(i); // (<i>internal copy of p</i>)->f(i)
</pre>
<p>
The last two examples are interesting in that they produce "self-contained"
function objects. <tt>bind(&amp;X::f, x, _1)</tt> stores a copy of <b>x</b>.
<tt>bind(&amp;X::f, p, _1)</tt> stores a copy of <b>p</b>, and since <b>p</b>
is a
<a href="../smart_ptr/shared_ptr.htm">boost::shared_ptr</a>,
the function object retains a reference to its instance of <b>X</b> and will
remain valid even when <b>p</b> goes out of scope or is <b>reset()</b>.
</p>
<h3>Using nested binds for function composition</h3>
<p>
Some of the arguments passed to <b>bind</b> may be nested <b>bind</b> expressions
themselves:
</p>
<pre>
bind(f, bind(g, _1))(x); // f(g(x))
</pre>
<p>
The nested subexpressions are evaluated when the function object is called. This
feature of <b>bind</b> can be used to perform function composition.
</p>
<p>
See <a href="bind_as_compose.cpp">bind_as_compose.cpp</a> for an example that
demonstrates how to use <b>bind</b> to achieve similar functionality to
<a href="../compose/index.htm">Boost.Compose</a>.
</p>
<p>
Note that the <b>first</b> argument - the bound function object - is an
exception to the nesting rules. A nested <b>bind</b> expression passed
to <b>bind</b> as a first argument is <b>not</b> treated differently from
any other function object:
</p>
<pre>
int x = 4;
template&lt;class F&gt; void test(F f)
{
bind(f, 5)(x);
}
int g(int, int);
int main()
{
test(bind(g, _1, 8)); // g(5, 8) and not g(x, 8)(5)
}
</pre>
<h3>Example: using bind with standard algorithms</h3>
<pre>
class image;
class animation
{
public:
void advance(int ms);
bool inactive() const;
void render(image &amp; target) const;
};
std::vector&lt;animation&gt; anims;
template&lt;class C, class P&gt; void erase_if(C &amp; c, P pred)
{
c.erase(std::remove_if(c.begin(), c.end(), pred), c.end());
}
void update(int ms)
{
std::for_each(anims.begin(), anims.end(), boost::bind(&amp;animation::advance, _1, ms));
erase_if(anims, boost::mem_fn(&amp;animation::inactive));
}
void render(image &amp; target)
{
std::for_each(anims.begin(), anims.end(), boost::bind(&amp;animation::render, _1, boost::ref(target)));
}
</pre>
<h3>Example: using bind with Boost.Function</h3>
<pre>
class button
{
public:
<a href="../function/index.html">boost::function</a>&lt;void&gt; onClick;
};
class player
{
public:
void play();
void stop();
};
button playButton, stopButton;
player thePlayer;
void connect()
{
playButton.onClick = boost::bind(&amp;player::play, &amp;thePlayer);
stopButton.onClick = boost::bind(&amp;player::stop, &amp;thePlayer);
}
</pre>
<h3>Limitations</h3>
<p>
The function objects generated by <b>bind</b> take their arguments by
reference and cannot, therefore, accept non-const temporaries or literal
constants. This is an inherent limitation of the C++ language, known as the
"forwarding function problem."
</p>
<p>
The library uses signatures of the form
</p>
<pre>
template&lt;class T&gt; void f(T &amp; t);
</pre>
<p>
to accept arguments of arbitrary types and pass them on unmodified. As noted,
this does not work with non-const r-values.
</p>
<p>
An oft-proposed "solution" to this problem is to add an overload:
</p>
<pre>
template&lt;class T&gt; void f(T &amp; t);
template&lt;class T&gt; void f(T const &amp; t);
</pre>
<p>
Unfortunately, this (a) requires providing 512 overloads for nine arguments
and (b) does not actually work for const arguments, both l- and r-values,
since the two templates produce the exact same signature and cannot be
partially ordered.
</p>
<p>
[Note: this is a dark corner of the language, and the
<a href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#214">
corresponding issue</a> has not been resolved yet.]
</p>
<h2>Interface</h2>
<h3>Synopsis</h3>
<pre>
namespace boost
{
// no arguments
template&lt;class R, class F&gt; <i>implementation-defined-1</i> <a href="#bind_1">bind</a>(F f);
template&lt;class R&gt; <i>implementation-defined-2</i> <a href="#bind_2">bind</a>(R (*f) ());
// one argument
template&lt;class R, class F, class A1&gt; <i>implementation-defined-3</i> <a href="#bind_3">bind</a>(F f, A1 a1);
template&lt;class R, class B1, class A1&gt; <i>implementation-defined-4</i> <a href="#bind_4">bind</a>(R (*f) (B1), A1 a1);
template&lt;class R, class T, class A1&gt; <i>implementation-defined-5</i> <a href="#bind_5">bind</a>(R (T::*f) (), A1 a1);
template&lt;class R, class T, class A1&gt; <i>implementation-defined-6</i> <a href="#bind_6">bind</a>(R (T::*f) () const, A1 a1);
// two arguments
template&lt;class R, class F, class A1, class A2&gt; <i>implementation-defined-7</i> <a href="#bind_7">bind</a>(F f, A1 a1, A2 a2);
template&lt;class R, class B1, class B2, class A1, class A2&gt; <i>implementation-defined-8</i> <a href="#bind_8">bind</a>(R (*f) (B1, B2), A1 a1, A2 a2);
template&lt;class R, class T, class B1, class A1, class A2&gt; <i>implementation-defined-9</i> <a href="#bind_9">bind</a>(R (T::*f) (B1), A1 a1, A2 a2);
template&lt;class R, class T, class B1, class A1, class A2&gt; <i>implementation-defined-10</i> <a href="#bind_10">bind</a>(R (T::*f) (B1) const, A1 a1, A2 a2);
// implementation defined number of additional overloads for more arguments
}
namespace
{
<i>implementation-defined-placeholder-type-1</i> _1;
<i>implementation-defined-placeholder-type-2</i> _2;
<i>implementation-defined-placeholder-type-3</i> _3;
// implementation defined number of additional placeholder definitions
}
</pre>
<h3>Common requirements</h3>
<p>
All <tt><i>implementation-defined-N</i></tt> types returned by <b>bind</b> are
<b>CopyConstructible</b>. <tt><i>implementation-defined-N</i>::result_type</tt> is defined as
the return type of <tt><i>implementation-defined-N</i>::operator()</tt>.
</p>
<p>
All <tt><i>implementation-defined-placeholder-N</i></tt> types are
<b>CopyConstructible</b>. Their copy constructors do not throw exceptions.
</p>
<h3>Common definitions</h3>
<p>
The function &micro;(x, v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>), where m is a nonnegative integer, is defined as:
</p>
<ul>
<li><tt>x.get()</tt>, when <tt>x</tt> is of type
<tt><a href="ref.html">boost::reference_wrapper</a>&lt;T&gt;</tt> for some type <tt>T</tt>;</li>
<li>v<sub>k</sub>, when <tt>x</tt> is (a copy of) the placeholder _k for some positive integer k;</li>
<li><tt>x(v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>)</tt>
when <tt>x</tt> is (a copy of) a function object returned by <b>bind</b>;</li>
<li><tt>x</tt> otherwise.</li>
</ul>
<h3>bind</h3>
<h4><a name="bind_1">template&lt;class R, class F&gt; <i>implementation-defined-1</i> bind(F f)</a></h4>
<p>
<b>Returns:</b> a function object <i>&lambda;</i> such that the expression
<tt>&lambda;(v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>)</tt> is equivalent to <tt><b>f</b>()</tt>,
implicitly converted to <b>R</b>.
</p>
<p>
<b>Throws:</b> Nothing unless the copy constructor of <b>F</b> throws an exception.
</p>
<h4><a name="bind_2">template&lt;class R&gt; <i>implementation-defined-2</i> bind(R (*f) ())</a></h4>
<p>
<b>Returns:</b> a function object <i>&lambda;</i> such that the expression
<tt>&lambda;(v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>)</tt> is equivalent to <tt><b>f</b>()</tt>.
</p>
<p>
<b>Throws:</b> Nothing.
</p>
<h4><a name="bind_3">template&lt;class R, class F, class A1&gt; <i>implementation-defined-3</i> bind(F f, A1 a1)</a></h4>
<p>
<b>Returns:</b> a function object <i>&lambda;</i> such that the expression
<tt>&lambda;(v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>)</tt> is equivalent to
<tt><b>f</b>(&micro;(<b>a1</b>, v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>))</tt>,
implicitly converted to <b>R</b>.
</p>
<p>
<b>Throws:</b> Nothing unless the copy constructors of <b>F</b> and <b>A1</b> throw an exception.
</p>
<h4><a name="bind_4">template&lt;class R, class B1, class A1&gt; <i>implementation-defined-4</i> bind(R (*f) (B1), A1 a1)</a></h4>
<p>
<b>Returns:</b> a function object <i>&lambda;</i> such that the expression
<tt>&lambda;(v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>)</tt> is equivalent to
<tt><b>f</b>(&micro;(<b>a1</b>, v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>))</tt>.
</p>
<p>
<b>Throws:</b> Nothing unless the copy constructor of <b>A1</b> throws an exception.
</p>
<h4><a name="bind_5">template&lt;class R, class T, class A1&gt; <i>implementation-defined-5</i> bind(R (T::*f) (), A1 a1)</a></h4>
<p>
<b>Effects:</b> equivalent to <tt>bind&lt;R&gt;(<a href="mem_fn.html">boost::mem_fn</a>(f), a1);</tt>
</p>
<h4><a name="bind_6">template&lt;class R, class T, class A1&gt; <i>implementation-defined-6</i> bind(R (T::*f) () const, A1 a1)</a></h4>
<p>
<b>Effects:</b> equivalent to <tt>bind&lt;R&gt;(<a href="mem_fn.html">boost::mem_fn</a>(f), a1);</tt>
</p>
<h4><a name="bind_7">template&lt;class R, class F, class A1, class A2&gt; <i>implementation-defined-7</i> bind(F f, A1 a1, A2 a2)</a></h4>
<p>
<b>Returns:</b> a function object <i>&lambda;</i> such that the expression
<tt>&lambda;(v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>)</tt> is equivalent to
<tt><b>f</b>(&micro;(<b>a1</b>, v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>), &micro;(<b>a2</b>, v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>))</tt>,
implicitly converted to <b>R</b>.
</p>
<p>
<b>Throws:</b> Nothing unless the copy constructors of <b>F</b>, <b>A1</b> and <b>A2</b> throw an exception.
</p>
<h4><a name="bind_8">template&lt;class R, class B1, class B2, class A1, class A2&gt; <i>implementation-defined-8</i> bind(R (*f) (B1, B2), A1 a1, A2 a2)</a></h4>
<p>
<b>Returns:</b> a function object <i>&lambda;</i> such that the expression
<tt>&lambda;(v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>)</tt> is equivalent to
<tt><b>f</b>(&micro;(<b>a1</b>, v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>), &micro;(<b>a2</b>, v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>))</tt>.
</p>
<p>
<b>Throws:</b> Nothing unless the copy constructors of <b>A1</b> and <b>A2</b> throw an exception.
</p>
<h4><a name="bind_9">template&lt;class R, class T, class B1, class A1, class A2&gt; <i>implementation-defined-9</i> bind(R (T::*f) (B1), A1 a1, A2 a2)</a></h4>
<p>
<b>Effects:</b> equivalent to <tt>bind&lt;R&gt;(<a href="mem_fn.html">boost::mem_fn</a>(f), a1, a2);</tt>
</p>
<h4><a name="bind_10">template&lt;class R, class T, class B1, class A1, class A2&gt; <i>implementation-defined-10</i> bind(R (T::*f) (B1) const, A1 a1, A2 a2)</a></h4>
<p>
<b>Effects:</b> equivalent to <tt>bind&lt;R&gt;(<a href="mem_fn.html">boost::mem_fn</a>(f), a1, a2);</tt>
</p>
<h2>Implementation</h2>
<p>
This implementation supports function objects with up to nine arguments.
This is an implementation detail, not an inherent limitation of the
design.
</p>
<h3>Void returns</h3>
<p>
The following C++ code:
</p>
<pre>
void f();
void g()
{
return f();
}
</pre>
<p>
is legal; in fact it was deliberately made legal in order to support
forwarding functions that return <b>void</b>.
</p>
<p>
Unfortunately, some compilers have not caught up with the C++ Standard yet
and do not allow void returns. This implementation of <b>bind</b> will not
work for function pointers, member function pointers or function objects that
return <b>void</b> if the compiler does not support the feature. A possible
workaround is to change the return type of the function object in question
from <b>void</b> to <b>int</b> and return a dummy value of 0.
</p>
<h3>MSVC specific problems and workarounds</h3>
<p>
Microsoft Visual C++ (up to version 7.0) does not fully support the
<b>bind&lt;R&gt;(...)</b>
syntax required by the library when arbitrary function objects are bound.
The first problem is that when <b>boost::bind</b> is brought into scope
with an <b>using declaration</b>:
</p>
<pre>
using boost::bind;
</pre>
<p>
the syntax above does not work. Workaround: either use the qualified name,
<b>boost::bind</b>, or use an <b>using directive</b> instead:
</p>
<pre>
using namespace boost;
</pre>
<p>
The second problem is that some libraries contain nested class templates
named <b>bind</b> (ironically, such code is often an MSVC specific
workaround.) Due to some quirks with the parser, such a class template
breaks the <b>bind&lt;R&gt;(...)</b> syntax, even when the name <b>bind</b>
is fully qualified. You may try to patch the library in question or contact
its author/maintainer. The other option is to define the macro
<b>BOOST_BIND</b> to something other than <b>bind</b> (before the inclusion of
<b>&lt;boost/bind.hpp&gt;</b>) and use this identifier throughout your code
wherever you'd normally use <b>bind</b>.
</p>
<p style="color: Red;">
[Note: BOOST_BIND is not a general renaming mechanism. It is not part of the
interface, and is not guaranteed to work on other compilers, or persist between
library versions. In short, don't use it unless you absolutely have to.]
</p>
<h3>Visitor support</h3>
<p style="color: Red;">
[Note: this is an experimental feature. It may evolve over time
when other libraries start to exploit it; or it may be removed altogether if
no other library needs it. It is not part of the interface.]
</p>
<p>
For better integration with other libraries, the function objects returned by
<b>bind</b> define a member function
</p>
<pre>
template&lt;class Visitor&gt; void accept(Visitor &amp; v);
</pre>
<p>
that applies <b>v</b>, as a function object, to its internal state. Using
<b>accept</b> is implementation-specific and not intended for end users.
</p>
<p>
See <a href="bind_test_4.cpp">bind_test_4.cpp</a> for an example.
</p>
<h2>Acknowledgements</h2>
<p>
Earlier efforts that have influenced the library design:
</p>
<ul>
<li>The <a href="http://staff.cs.utu.fi/BL/">Binder Library</a>
by Jaakko J&auml;rvi;
<li>The <a href="http://lambda.cs.utu.fi/">Lambda Library</a>
by Jaakko J&auml;rvi and Gary Powell (the successor to the Binder Library);
<li><a href="http://matfys.lth.se/~petter/src/more/stlext/index.html">
Extensions to the STL</a> by Petter Urkedal.
</ul>
<p>
Doug Gregor suggested that a visitor mechanism would allow <b>bind</b> to
interoperate with a signal/slot library.
</p>
<p>
John Maddock fixed a MSVC-specific conflict between <b>bind</b> and the
<a href="../type_traits/index.htm">type traits library</a>.
</p>
<p>
Numerous improvements were suggested during the formal review period by
Ross Smith, Richard Crossley, Jens Maurer, Ed Brey, and others. Review manager
was Darin Adler.
</p>
<p>
The precise semantics of <b>bind</b> were refined in discussions with Jaakko J&auml;rvi.
</p>
<p><br><br><br><small>Copyright &copy; 2001 by Peter Dimov and Multi Media
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 &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose.</small></p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

75
bind_as_compose.cpp Normal file
View File

@@ -0,0 +1,75 @@
#if defined(_MSC_VER) && !defined(__ICL)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
//
// bind_as_compose.cpp - function composition using bind.hpp
//
// Version 1.00.0001 (2001-08-30)
//
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/bind.hpp>
#include <iostream>
#include <string>
std::string f(std::string const & x)
{
return "f(" + x + ")";
}
std::string g(std::string const & x)
{
return "g(" + x + ")";
}
std::string h(std::string const & x, std::string const & y)
{
return "h(" + x + ", " + y + ")";
}
std::string k()
{
return "k()";
}
template<class F> void test(F f)
{
std::cout << f("x", "y") << '\n';
}
int main()
{
using namespace boost;
// compose_f_gx
test( bind(f, bind(g, _1)) );
// compose_f_hxy
test( bind(f, bind(h, _1, _2)) );
// compose_h_fx_gx
test( bind(h, bind(f, _1), bind(g, _1)) );
// compose_h_fx_gy
test( bind(h, bind(f, _1), bind(g, _2)) );
// compose_f_k
test( bind(f, bind(k)) );
return 0;
}

269
bind_test.cpp Normal file
View File

@@ -0,0 +1,269 @@
#if defined(_MSC_VER) && !defined(__ICL)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
//
// bind_test.cpp - monolithic test for bind.hpp
//
// Version 1.00.0002 (2001-09-02)
//
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <iostream>
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
//
long f_0()
{
return 17041L;
}
long f_1(long a)
{
return a;
}
long f_2(long a, long b)
{
return a + 10 * b;
}
long f_3(long a, long b, long c)
{
return a + 10 * b + 100 * c;
}
long f_4(long a, long b, long c, long d)
{
return a + 10 * b + 100 * c + 1000 * d;
}
long f_5(long a, long b, long c, long d, long e)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e;
}
long f_6(long a, long b, long c, long d, long e, long f)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f;
}
long f_7(long a, long b, long c, long d, long e, long f, long g)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g;
}
long f_8(long a, long b, long c, long d, long e, long f, long g, long h)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g + 10000000 * h;
}
long f_9(long a, long b, long c, long d, long e, long f, long g, long h, long i)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g + 10000000 * h + 100000000 * i;
}
void function_test()
{
using namespace boost;
int const i = 1;
BOOST_TEST( bind(f_0)(i) == 17041L );
BOOST_TEST( bind(f_1, _1)(i) == 1L );
BOOST_TEST( bind(f_2, _1, 2)(i) == 21L );
BOOST_TEST( bind(f_3, _1, 2, 3)(i) == 321L );
BOOST_TEST( bind(f_4, _1, 2, 3, 4)(i) == 4321L );
BOOST_TEST( bind(f_5, _1, 2, 3, 4, 5)(i) == 54321L );
BOOST_TEST( bind(f_6, _1, 2, 3, 4, 5, 6)(i) == 654321L );
BOOST_TEST( bind(f_7, _1, 2, 3, 4, 5, 6, 7)(i) == 7654321L );
BOOST_TEST( bind(f_8, _1, 2, 3, 4, 5, 6, 7, 8)(i) == 87654321L );
BOOST_TEST( bind(f_9, _1, 2, 3, 4, 5, 6, 7, 8, 9)(i) == 987654321L );
}
//
struct Y
{
short operator()(short & r) const { return ++r; }
int operator()(int a, int b) const { return a + 10 * b; }
long operator() (long a, long b, long c) const { return a + 10 * b + 100 * c; }
};
void function_object_test()
{
using namespace boost;
short i(6);
int const k = 3;
BOOST_TEST( bind<short>(Y(), ref(i))() == 7 );
BOOST_TEST( bind<short>(Y(), ref(i))() == 8 );
BOOST_TEST( bind<int>(Y(), i, _1)(k) == 38 );
BOOST_TEST( bind<long>(Y(), i, _1, 9)(k) == 938 );
}
//
struct X
{
mutable unsigned int hash;
X(): hash(0) {}
int f0() { f1(17); return 0; }
int g0() const { g1(17); return 0; }
int f1(int a1) { hash = (hash * 17041 + a1) % 32768; return 0; }
int g1(int a1) const { hash = (hash * 17041 + a1 * 2) % 32768; return 0; }
int f2(int a1, int a2) { f1(a1); f1(a2); return 0; }
int g2(int a1, int a2) const { g1(a1); g1(a2); return 0; }
int f3(int a1, int a2, int a3) { f2(a1, a2); f1(a3); return 0; }
int g3(int a1, int a2, int a3) const { g2(a1, a2); g1(a3); return 0; }
int f4(int a1, int a2, int a3, int a4) { f3(a1, a2, a3); f1(a4); return 0; }
int g4(int a1, int a2, int a3, int a4) const { g3(a1, a2, a3); g1(a4); return 0; }
int f5(int a1, int a2, int a3, int a4, int a5) { f4(a1, a2, a3, a4); f1(a5); return 0; }
int g5(int a1, int a2, int a3, int a4, int a5) const { g4(a1, a2, a3, a4); g1(a5); return 0; }
int f6(int a1, int a2, int a3, int a4, int a5, int a6) { f5(a1, a2, a3, a4, a5); f1(a6); return 0; }
int g6(int a1, int a2, int a3, int a4, int a5, int a6) const { g5(a1, a2, a3, a4, a5); g1(a6); return 0; }
int f7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) { f6(a1, a2, a3, a4, a5, a6); f1(a7); return 0; }
int g7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) const { g6(a1, a2, a3, a4, a5, a6); g1(a7); return 0; }
int f8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { f7(a1, a2, a3, a4, a5, a6, a7); f1(a8); return 0; }
int g8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) const { g7(a1, a2, a3, a4, a5, a6, a7); g1(a8); return 0; }
};
void member_function_test()
{
using namespace boost;
X x;
// 0
bind(&X::f0, &x)();
bind(&X::f0, ref(x))();
bind(&X::g0, &x)();
bind(&X::g0, x)();
bind(&X::g0, ref(x))();
// 1
bind(&X::f1, &x, 1)();
bind(&X::f1, ref(x), 1)();
bind(&X::g1, &x, 1)();
bind(&X::g1, x, 1)();
bind(&X::g1, ref(x), 1)();
// 2
bind(&X::f2, &x, 1, 2)();
bind(&X::f2, ref(x), 1, 2)();
bind(&X::g2, &x, 1, 2)();
bind(&X::g2, x, 1, 2)();
bind(&X::g2, ref(x), 1, 2)();
// 3
bind(&X::f3, &x, 1, 2, 3)();
bind(&X::f3, ref(x), 1, 2, 3)();
bind(&X::g3, &x, 1, 2, 3)();
bind(&X::g3, x, 1, 2, 3)();
bind(&X::g3, ref(x), 1, 2, 3)();
// 4
bind(&X::f4, &x, 1, 2, 3, 4)();
bind(&X::f4, ref(x), 1, 2, 3, 4)();
bind(&X::g4, &x, 1, 2, 3, 4)();
bind(&X::g4, x, 1, 2, 3, 4)();
bind(&X::g4, ref(x), 1, 2, 3, 4)();
// 5
bind(&X::f5, &x, 1, 2, 3, 4, 5)();
bind(&X::f5, ref(x), 1, 2, 3, 4, 5)();
bind(&X::g5, &x, 1, 2, 3, 4, 5)();
bind(&X::g5, x, 1, 2, 3, 4, 5)();
bind(&X::g5, ref(x), 1, 2, 3, 4, 5)();
// 6
bind(&X::f6, &x, 1, 2, 3, 4, 5, 6)();
bind(&X::f6, ref(x), 1, 2, 3, 4, 5, 6)();
bind(&X::g6, &x, 1, 2, 3, 4, 5, 6)();
bind(&X::g6, x, 1, 2, 3, 4, 5, 6)();
bind(&X::g6, ref(x), 1, 2, 3, 4, 5, 6)();
// 7
bind(&X::f7, &x, 1, 2, 3, 4, 5, 6, 7)();
bind(&X::f7, ref(x), 1, 2, 3, 4, 5, 6, 7)();
bind(&X::g7, &x, 1, 2, 3, 4, 5, 6, 7)();
bind(&X::g7, x, 1, 2, 3, 4, 5, 6, 7)();
bind(&X::g7, ref(x), 1, 2, 3, 4, 5, 6, 7)();
// 8
bind(&X::f8, &x, 1, 2, 3, 4, 5, 6, 7, 8)();
bind(&X::f8, ref(x), 1, 2, 3, 4, 5, 6, 7, 8)();
bind(&X::g8, &x, 1, 2, 3, 4, 5, 6, 7, 8)();
bind(&X::g8, x, 1, 2, 3, 4, 5, 6, 7, 8)();
bind(&X::g8, ref(x), 1, 2, 3, 4, 5, 6, 7, 8)();
BOOST_TEST( x.hash == 23558 );
}
void nested_bind_test()
{
using namespace boost;
int const x = 1;
int const y = 2;
BOOST_TEST( bind(f_1, bind(f_1, _1))(x) == 1L );
BOOST_TEST( bind(f_1, bind(f_2, _1, _2))(x, y) == 21L );
BOOST_TEST( bind(f_2, bind(f_1, _1), bind(f_1, _1))(x) == 11L );
BOOST_TEST( bind(f_2, bind(f_1, _1), bind(f_1, _2))(x, y) == 21L );
BOOST_TEST( bind(f_1, bind(f_0))() == 17041L );
}
int test_main(int, char * [])
{
function_test();
function_object_test();
member_function_test();
nested_bind_test();
return 0;
}

104
bind_test_1.cpp Normal file
View File

@@ -0,0 +1,104 @@
#if defined(_MSC_VER) && !defined(__ICL)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
//
// bind_test_1.cpp - tests bind.hpp with function pointers
//
// Version 1.00.0003 (2001-07-13)
//
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/bind.hpp>
#include <iostream>
long f_1(long a)
{
return a;
}
long f_2(long a, long b)
{
return a + 10 * b;
}
long f_3(long a, long b, long c)
{
return a + 10 * b + 100 * c;
}
long f_4(long a, long b, long c, long d)
{
return a + 10 * b + 100 * c + 1000 * d;
}
long f_5(long a, long b, long c, long d, long e)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e;
}
long f_6(long a, long b, long c, long d, long e, long f)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f;
}
long f_7(long a, long b, long c, long d, long e, long f, long g)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g;
}
long f_8(long a, long b, long c, long d, long e, long f, long g, long h)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g + 10000000 * h;
}
long f_9(long a, long b, long c, long d, long e, long f, long g, long h, long i)
{
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g + 10000000 * h + 100000000 * i;
}
unsigned long hash = 0;
template<class F> void test(F f)
{
int const i = 1;
hash = (hash * 17041 + f(i)) % 32768;
}
int detect_errors(bool x)
{
if(x)
{
std::cerr << "no errors detected.\n";
return 0;
}
else
{
std::cerr << "test failed.\n";
return 1;
}
}
int main()
{
test(boost::bind(f_1, _1));
test(boost::bind(f_2, _1, 2));
test(boost::bind(f_3, _1, 2, 3));
test(boost::bind(f_4, _1, 2, 3, 4));
test(boost::bind(f_5, _1, 2, 3, 4, 5));
test(boost::bind(f_6, _1, 2, 3, 4, 5, 6));
test(boost::bind(f_7, _1, 2, 3, 4, 5, 6, 7));
test(boost::bind(f_8, _1, 2, 3, 4, 5, 6, 7, 8));
test(boost::bind(f_9, _1, 2, 3, 4, 5, 6, 7, 8, 9));
return detect_errors(hash == 18797);
}

65
bind_test_2.cpp Normal file
View File

@@ -0,0 +1,65 @@
#if defined(_MSC_VER) && !defined(__ICL)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
//
// bind_test_2.cpp - tests bind.hpp with function objects
//
// Version 1.00.0005 (2001-07-13)
//
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <iostream>
struct X
{
short operator()(short & r) const { return ++r; }
int operator()(int a, int b) const { return a + 10 * b; }
long operator() (long a, long b, long c) const { return a + 10 * b + 100 * c; }
};
unsigned long hash = 0;
template<class F> void test(F f, int const i)
{
hash = (hash * 17041 + f(i)) % 32768;
}
int detect_errors(bool x)
{
if(x)
{
std::cerr << "no errors detected.\n";
return 0;
}
else
{
std::cerr << "test failed.\n";
return 1;
}
}
int main()
{
using namespace boost;
short i(6);
test(bind<short>(X(), ref(i)), 1);
test(bind<short>(X(), ref(i)), 2);
test(bind<int>(X(), i, _1), 3);
test(bind<long>(X(), i, _1, 9), 4);
return detect_errors(hash == 24857);
}

161
bind_test_3.cpp Normal file
View File

@@ -0,0 +1,161 @@
#if defined(_MSC_VER) && !defined(__ICL)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
//
// bind_test_3.cpp - tests bind.hpp with member function pointers
//
// Version 1.00.0003 (2001-07-13)
//
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <iostream>
struct X
{
mutable unsigned int hash;
X(): hash(0) {}
int f0() { f1(17); return 0; }
int g0() const { g1(17); return 0; }
int f1(int a1) { hash = (hash * 17041 + a1) % 32768; return 0; }
int g1(int a1) const { hash = (hash * 17041 + a1 * 2) % 32768; return 0; }
int f2(int a1, int a2) { f1(a1); f1(a2); return 0; }
int g2(int a1, int a2) const { g1(a1); g1(a2); return 0; }
int f3(int a1, int a2, int a3) { f2(a1, a2); f1(a3); return 0; }
int g3(int a1, int a2, int a3) const { g2(a1, a2); g1(a3); return 0; }
int f4(int a1, int a2, int a3, int a4) { f3(a1, a2, a3); f1(a4); return 0; }
int g4(int a1, int a2, int a3, int a4) const { g3(a1, a2, a3); g1(a4); return 0; }
int f5(int a1, int a2, int a3, int a4, int a5) { f4(a1, a2, a3, a4); f1(a5); return 0; }
int g5(int a1, int a2, int a3, int a4, int a5) const { g4(a1, a2, a3, a4); g1(a5); return 0; }
int f6(int a1, int a2, int a3, int a4, int a5, int a6) { f5(a1, a2, a3, a4, a5); f1(a6); return 0; }
int g6(int a1, int a2, int a3, int a4, int a5, int a6) const { g5(a1, a2, a3, a4, a5); g1(a6); return 0; }
int f7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) { f6(a1, a2, a3, a4, a5, a6); f1(a7); return 0; }
int g7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) const { g6(a1, a2, a3, a4, a5, a6); g1(a7); return 0; }
int f8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { f7(a1, a2, a3, a4, a5, a6, a7); f1(a8); return 0; }
int g8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) const { g7(a1, a2, a3, a4, a5, a6, a7); g1(a8); return 0; }
};
int detect_errors(bool x)
{
if(x)
{
std::cerr << "no errors detected.\n";
return 0;
}
else
{
std::cerr << "test failed.\n";
return 1;
}
}
int main()
{
using namespace boost;
X x;
// 0
bind(&X::f0, &x)();
bind(&X::f0, ref(x))();
bind(&X::g0, &x)();
bind(&X::g0, x)();
bind(&X::g0, ref(x))();
// 1
bind(&X::f1, &x, 1)();
bind(&X::f1, ref(x), 1)();
bind(&X::g1, &x, 1)();
bind(&X::g1, x, 1)();
bind(&X::g1, ref(x), 1)();
// 2
bind(&X::f2, &x, 1, 2)();
bind(&X::f2, ref(x), 1, 2)();
bind(&X::g2, &x, 1, 2)();
bind(&X::g2, x, 1, 2)();
bind(&X::g2, ref(x), 1, 2)();
// 3
bind(&X::f3, &x, 1, 2, 3)();
bind(&X::f3, ref(x), 1, 2, 3)();
bind(&X::g3, &x, 1, 2, 3)();
bind(&X::g3, x, 1, 2, 3)();
bind(&X::g3, ref(x), 1, 2, 3)();
// 4
bind(&X::f4, &x, 1, 2, 3, 4)();
bind(&X::f4, ref(x), 1, 2, 3, 4)();
bind(&X::g4, &x, 1, 2, 3, 4)();
bind(&X::g4, x, 1, 2, 3, 4)();
bind(&X::g4, ref(x), 1, 2, 3, 4)();
// 5
bind(&X::f5, &x, 1, 2, 3, 4, 5)();
bind(&X::f5, ref(x), 1, 2, 3, 4, 5)();
bind(&X::g5, &x, 1, 2, 3, 4, 5)();
bind(&X::g5, x, 1, 2, 3, 4, 5)();
bind(&X::g5, ref(x), 1, 2, 3, 4, 5)();
// 6
bind(&X::f6, &x, 1, 2, 3, 4, 5, 6)();
bind(&X::f6, ref(x), 1, 2, 3, 4, 5, 6)();
bind(&X::g6, &x, 1, 2, 3, 4, 5, 6)();
bind(&X::g6, x, 1, 2, 3, 4, 5, 6)();
bind(&X::g6, ref(x), 1, 2, 3, 4, 5, 6)();
// 7
bind(&X::f7, &x, 1, 2, 3, 4, 5, 6, 7)();
bind(&X::f7, ref(x), 1, 2, 3, 4, 5, 6, 7)();
bind(&X::g7, &x, 1, 2, 3, 4, 5, 6, 7)();
bind(&X::g7, x, 1, 2, 3, 4, 5, 6, 7)();
bind(&X::g7, ref(x), 1, 2, 3, 4, 5, 6, 7)();
// 8
bind(&X::f8, &x, 1, 2, 3, 4, 5, 6, 7, 8)();
bind(&X::f8, ref(x), 1, 2, 3, 4, 5, 6, 7, 8)();
bind(&X::g8, &x, 1, 2, 3, 4, 5, 6, 7, 8)();
bind(&X::g8, x, 1, 2, 3, 4, 5, 6, 7, 8)();
bind(&X::g8, ref(x), 1, 2, 3, 4, 5, 6, 7, 8)();
return detect_errors(x.hash == 23558);
}

89
bind_test_4.cpp Normal file
View File

@@ -0,0 +1,89 @@
#if defined(_MSC_VER) && !defined(__ICL)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
//
// bind_test_4.cpp - tests bind.hpp with a visitor
//
// Version 1.00.0003 (2001-08-30)
//
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#include <iostream>
#include <typeinfo>
int hash = 0;
struct ref_visitor
{
template<class R, class F, class L> void operator()(boost::_bi::bind_t<R, F, L> const & b) const
{
b.accept(*this);
}
template<class T> void operator()(boost::reference_wrapper<T> const & r) const
{
std::cout << "Reference to " << typeid(T).name() << " @ " << &r.get() << " (with value " << r.get() << ")\n";
hash += r.get();
}
#ifndef BOOST_MSVC
template<class T> void operator()(T const &) const
{
std::cout << "Catch-all: " << typeid(T).name() << '\n';
}
#else
void operator()(...) const
{
}
#endif
};
int f(int & i, int & j)
{
++i;
--j;
return i + j;
}
int x = 2;
int y = 7;
int detect_errors(bool x)
{
if(x)
{
std::cerr << "no errors detected.\n";
return 0;
}
else
{
std::cerr << "test failed.\n";
return 1;
}
}
int main()
{
using namespace boost;
ref_visitor()(bind<int>(bind(f, ref(x), _1), ref(y)));
return detect_errors(hash == 9);
}

1255
include/boost/bind.hpp Normal file

File diff suppressed because it is too large Load Diff

704
include/boost/mem_fn.hpp Normal file
View File

@@ -0,0 +1,704 @@
#ifndef BOOST_MEM_FN_HPP_INCLUDED
#define BOOST_MEM_FN_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// mem_fn.hpp - a generalization of std::mem_fun[_ref]
//
// Version 1.02.0001 (2001-08-30)
//
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// See http://www.boost.org/libs/bind/mem_fn.html for documentation.
//
namespace boost
{
// get_pointer(p) extracts a ->* capable pointer from p
template<class T> T * get_pointer(T * p)
{
return p;
}
// implementation of get_pointer for boost::shared_ptr
// this will probably migrate to boost/shared_ptr.hpp
template<class T> class shared_ptr;
template<class T> T * get_pointer(shared_ptr<T> const & p)
{
return p.get();
}
//
namespace _mfi // mem_fun_impl
{
// mf0
template<class R, class T> class mf0
{
public:
typedef R result_type;
typedef T * first_argument_type;
private:
typedef R (T::*F) ();
F f_;
public:
explicit mf0(F f): f_(f) {}
R operator()(T * p) const
{
return (p->*f_)();
}
template<class U> R operator()(U & u) const
{
return (get_pointer(u)->*f_)();
}
R operator()(T & t) const
{
return (t.*f_)();
}
};
// cmf0
template<class R, class T> class cmf0
{
public:
typedef R result_type;
typedef T const * first_argument_type;
private:
typedef R (T::*F) () const;
F f_;
public:
explicit cmf0(F f): f_(f) {}
template<class U> R operator()(U const & u) const
{
return (get_pointer(u)->*f_)();
}
R operator()(T const & t) const
{
return (t.*f_)();
}
};
// mf1
template<class R, class T, class A1> class mf1
{
public:
typedef R result_type;
typedef T * first_argument_type;
typedef A1 second_argument_type;
private:
typedef R (T::*F) (A1);
F f_;
public:
explicit mf1(F f): f_(f) {}
R operator()(T * p, A1 a1) const
{
return (p->*f_)(a1);
}
template<class U> R operator()(U & u, A1 a1) const
{
return (get_pointer(u)->*f_)(a1);
}
R operator()(T & t, A1 a1) const
{
return (t.*f_)(a1);
}
};
// cmf1
template<class R, class T, class A1> class cmf1
{
public:
typedef R result_type;
typedef T const * first_argument_type;
typedef A1 second_argument_type;
private:
typedef R (T::*F) (A1) const;
F f_;
public:
explicit cmf1(F f): f_(f) {}
template<class U> R operator()(U const & u, A1 a1) const
{
return (get_pointer(u)->*f_)(a1);
}
R operator()(T const & t, A1 a1) const
{
return (t.*f_)(a1);
}
};
// mf2
template<class R, class T, class A1, class A2> class mf2
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2);
F f_;
public:
explicit mf2(F f): f_(f) {}
R operator()(T * p, A1 a1, A2 a2) const
{
return (p->*f_)(a1, a2);
}
template<class U> R operator()(U & u, A1 a1, A2 a2) const
{
return (get_pointer(u)->*f_)(a1, a2);
}
R operator()(T & t, A1 a1, A2 a2) const
{
return (t.*f_)(a1, a2);
}
};
// cmf2
template<class R, class T, class A1, class A2> class cmf2
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2) const;
F f_;
public:
explicit cmf2(F f): f_(f) {}
template<class U> R operator()(U const & u, A1 a1, A2 a2) const
{
return (get_pointer(u)->*f_)(a1, a2);
}
R operator()(T const & t, A1 a1, A2 a2) const
{
return (t.*f_)(a1, a2);
}
};
// mf3
template<class R, class T, class A1, class A2, class A3> class mf3
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2, A3);
F f_;
public:
explicit mf3(F f): f_(f) {}
R operator()(T * p, A1 a1, A2 a2, A3 a3) const
{
return (p->*f_)(a1, a2, a3);
}
template<class U> R operator()(U & u, A1 a1, A2 a2, A3 a3) const
{
return (get_pointer(u)->*f_)(a1, a2, a3);
}
R operator()(T & t, A1 a1, A2 a2, A3 a3) const
{
return (t.*f_)(a1, a2, a3);
}
};
// cmf3
template<class R, class T, class A1, class A2, class A3> class cmf3
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2, A3) const;
F f_;
public:
explicit cmf3(F f): f_(f) {}
template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3) const
{
return (get_pointer(u)->*f_)(a1, a2, a3);
}
R operator()(T const & t, A1 a1, A2 a2, A3 a3) const
{
return (t.*f_)(a1, a2, a3);
}
};
// mf4
template<class R, class T, class A1, class A2, class A3, class A4> class mf4
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2, A3, A4);
F f_;
public:
explicit mf4(F f): f_(f) {}
R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4) const
{
return (p->*f_)(a1, a2, a3, a4);
}
template<class U> R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4) const
{
return (get_pointer(u)->*f_)(a1, a2, a3, a4);
}
R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4) const
{
return (t.*f_)(a1, a2, a3, a4);
}
};
// cmf4
template<class R, class T, class A1, class A2, class A3, class A4> class cmf4
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2, A3, A4) const;
F f_;
public:
explicit cmf4(F f): f_(f) {}
template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4) const
{
return (get_pointer(u)->*f_)(a1, a2, a3, a4);
}
R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4) const
{
return (t.*f_)(a1, a2, a3, a4);
}
};
// mf5
template<class R, class T, class A1, class A2, class A3, class A4, class A5> class mf5
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2, A3, A4, A5);
F f_;
public:
explicit mf5(F f): f_(f) {}
R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
{
return (p->*f_)(a1, a2, a3, a4, a5);
}
template<class U> R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
{
return (get_pointer(u)->*f_)(a1, a2, a3, a4, a5);
}
R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
{
return (t.*f_)(a1, a2, a3, a4, a5);
}
};
// cmf5
template<class R, class T, class A1, class A2, class A3, class A4, class A5> class cmf5
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2, A3, A4, A5) const;
F f_;
public:
explicit cmf5(F f): f_(f) {}
template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
{
return (get_pointer(u)->*f_)(a1, a2, a3, a4, a5);
}
R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) const
{
return (t.*f_)(a1, a2, a3, a4, a5);
}
};
// mf6
template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6> class mf6
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2, A3, A4, A5, A6);
F f_;
public:
explicit mf6(F f): f_(f) {}
R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
{
return (p->*f_)(a1, a2, a3, a4, a5, a6);
}
template<class U> R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
{
return (get_pointer(u)->*f_)(a1, a2, a3, a4, a5, a6);
}
R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
{
return (t.*f_)(a1, a2, a3, a4, a5, a6);
}
};
// cmf6
template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6> class cmf6
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2, A3, A4, A5, A6) const;
F f_;
public:
explicit cmf6(F f): f_(f) {}
template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
{
return (get_pointer(u)->*f_)(a1, a2, a3, a4, a5, a6);
}
R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) const
{
return (t.*f_)(a1, a2, a3, a4, a5, a6);
}
};
// mf7
template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> class mf7
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2, A3, A4, A5, A6, A7);
F f_;
public:
explicit mf7(F f): f_(f) {}
R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
{
return (p->*f_)(a1, a2, a3, a4, a5, a6, a7);
}
template<class U> R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
{
return (get_pointer(u)->*f_)(a1, a2, a3, a4, a5, a6, a7);
}
R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
{
return (t.*f_)(a1, a2, a3, a4, a5, a6, a7);
}
};
// cmf7
template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> class cmf7
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2, A3, A4, A5, A6, A7) const;
F f_;
public:
explicit cmf7(F f): f_(f) {}
template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
{
return (get_pointer(u)->*f_)(a1, a2, a3, a4, a5, a6, a7);
}
R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) const
{
return (t.*f_)(a1, a2, a3, a4, a5, a6, a7);
}
};
// mf8
template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> class mf8
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2, A3, A4, A5, A6, A7, A8);
F f_;
public:
explicit mf8(F f): f_(f) {}
R operator()(T * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
{
return (p->*f_)(a1, a2, a3, a4, a5, a6, a7, a8);
}
template<class U> R operator()(U & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
{
return (get_pointer(u)->*f_)(a1, a2, a3, a4, a5, a6, a7, a8);
}
R operator()(T & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
{
return (t.*f_)(a1, a2, a3, a4, a5, a6, a7, a8);
}
};
// cmf8
template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> class cmf8
{
public:
typedef R result_type;
private:
typedef R (T::*F) (A1, A2, A3, A4, A5, A6, A7, A8) const;
F f_;
public:
explicit cmf8(F f): f_(f) {}
R operator()(T const * p, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
{
return (p->*f_)(a1, a2, a3, a4, a5, a6, a7, a8);
}
template<class U> R operator()(U const & u, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
{
return (get_pointer(u)->*f_)(a1, a2, a3, a4, a5, a6, a7, a8);
}
R operator()(T const & t, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) const
{
return (t.*f_)(a1, a2, a3, a4, a5, a6, a7, a8);
}
};
} // namespace _mfi
// mem_fn
template<class R, class T> _mfi::mf0<R, T> mem_fn(R (T::*f) ())
{
return _mfi::mf0<R, T>(f);
}
template<class R, class T> _mfi::cmf0<R, T> mem_fn(R (T::*f) () const)
{
return _mfi::cmf0<R, T>(f);
}
template<class R, class T, class A1> _mfi::mf1<R, T, A1> mem_fn(R (T::*f) (A1))
{
return _mfi::mf1<R, T, A1>(f);
}
template<class R, class T, class A1> _mfi::cmf1<R, T, A1> mem_fn(R (T::*f) (A1) const)
{
return _mfi::cmf1<R, T, A1>(f);
}
template<class R, class T, class A1, class A2> _mfi::mf2<R, T, A1, A2> mem_fn(R (T::*f) (A1, A2))
{
return _mfi::mf2<R, T, A1, A2>(f);
}
template<class R, class T, class A1, class A2> _mfi::cmf2<R, T, A1, A2> mem_fn(R (T::*f) (A1, A2) const)
{
return _mfi::cmf2<R, T, A1, A2>(f);
}
template<class R, class T, class A1, class A2, class A3> _mfi::mf3<R, T, A1, A2, A3> mem_fn(R (T::*f) (A1, A2, A3))
{
return _mfi::mf3<R, T, A1, A2, A3>(f);
}
template<class R, class T, class A1, class A2, class A3> _mfi::cmf3<R, T, A1, A2, A3> mem_fn(R (T::*f) (A1, A2, A3) const)
{
return _mfi::cmf3<R, T, A1, A2, A3>(f);
}
template<class R, class T, class A1, class A2, class A3, class A4> _mfi::mf4<R, T, A1, A2, A3, A4> mem_fn(R (T::*f) (A1, A2, A3, A4))
{
return _mfi::mf4<R, T, A1, A2, A3, A4>(f);
}
template<class R, class T, class A1, class A2, class A3, class A4> _mfi::cmf4<R, T, A1, A2, A3, A4> mem_fn(R (T::*f) (A1, A2, A3, A4) const)
{
return _mfi::cmf4<R, T, A1, A2, A3, A4>(f);
}
template<class R, class T, class A1, class A2, class A3, class A4, class A5> _mfi::mf5<R, T, A1, A2, A3, A4, A5> mem_fn(R (T::*f) (A1, A2, A3, A4, A5))
{
return _mfi::mf5<R, T, A1, A2, A3, A4, A5>(f);
}
template<class R, class T, class A1, class A2, class A3, class A4, class A5> _mfi::cmf5<R, T, A1, A2, A3, A4, A5> mem_fn(R (T::*f) (A1, A2, A3, A4, A5) const)
{
return _mfi::cmf5<R, T, A1, A2, A3, A4, A5>(f);
}
template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6> _mfi::mf6<R, T, A1, A2, A3, A4, A5, A6> mem_fn(R (T::*f) (A1, A2, A3, A4, A5, A6))
{
return _mfi::mf6<R, T, A1, A2, A3, A4, A5, A6>(f);
}
template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6> _mfi::cmf6<R, T, A1, A2, A3, A4, A5, A6> mem_fn(R (T::*f) (A1, A2, A3, A4, A5, A6) const)
{
return _mfi::cmf6<R, T, A1, A2, A3, A4, A5, A6>(f);
}
template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> _mfi::mf7<R, T, A1, A2, A3, A4, A5, A6, A7> mem_fn(R (T::*f) (A1, A2, A3, A4, A5, A6, A7))
{
return _mfi::mf7<R, T, A1, A2, A3, A4, A5, A6, A7>(f);
}
template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7> _mfi::cmf7<R, T, A1, A2, A3, A4, A5, A6, A7> mem_fn(R (T::*f) (A1, A2, A3, A4, A5, A6, A7) const)
{
return _mfi::cmf7<R, T, A1, A2, A3, A4, A5, A6, A7>(f);
}
template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> _mfi::mf8<R, T, A1, A2, A3, A4, A5, A6, A7, A8> mem_fn(R (T::*f) (A1, A2, A3, A4, A5, A6, A7, A8))
{
return _mfi::mf8<R, T, A1, A2, A3, A4, A5, A6, A7, A8>(f);
}
template<class R, class T, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> _mfi::cmf8<R, T, A1, A2, A3, A4, A5, A6, A7, A8> mem_fn(R (T::*f) (A1, A2, A3, A4, A5, A6, A7, A8) const)
{
return _mfi::cmf8<R, T, A1, A2, A3, A4, A5, A6, A7, A8>(f);
}
} // namespace boost
#endif // #ifndef BOOST_MEM_FN_HPP_INCLUDED

282
mem_fn.html Normal file
View File

@@ -0,0 +1,282 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Boost: mem_fn.hpp documentation</title>
</head>
<body bgcolor="White">
<table border="0" width="100%">
<tr>
<td align="center">
<table border="0" width="90%">
<tr>
<td width="277">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" WIDTH="277" HEIGHT="86">
</td>
<td align="center">
<table border="0">
<tr><td nowrap><h1>mem_fn.hpp</h1></td></tr>
<tr><td align="right" nowrap><small>&nbsp;1.02.0001 (2001-08-30)</small></td></tr>
</table>
</td>
</tr>
<tr>
<td height="64">&nbsp;</td>
</tr>
</table>
<table border="0" width="90%">
<tr>
<td>
<h2>Files</h2>
<ul>
<li><a href="../../boost/mem_fn.hpp">mem_fn.hpp</a> (implementation)
<li><a href="mem_fn_test.cpp">mem_fn_test.cpp</a> (test)
</ul>
<h2>Purpose</h2>
<p>
<b>boost::mem_fn</b> is a generalization of the standard functions
<b>std::mem_fun</b> and <b>std::mem_fun_ref</b>. It supports member
function pointers with more than one argument, and the returned function
object can take a pointer, a reference, or a smart pointer to an object
instance as its first argument.
</p>
<p>
<b>mem_fn</b> takes one argument, a pointer to a member function, and
returns a function object suitable for use with standard or user-defined
algorithms:
</p>
<pre>
struct X
{
void f();
};
void g(std::vector&lt;X&gt; &amp; v)
{
std::for_each(v.begin(), v.end(), boost::mem_fn(&amp;X::f));
};
void h(std::vector&lt;X *&gt; const &amp; v)
{
std::for_each(v.begin(), v.end(), boost::mem_fn(&amp;X::f));
};
void k(std::vector&lt;boost::shared_ptr&lt;X&gt; &gt; const &amp; v)
{
std::for_each(v.begin(), v.end(), boost::mem_fn(&amp;X::f));
};
</pre>
<p>
The returned function object takes the same arguments as the input member
function plus a "flexible" first argument that represents the object instance.
</p>
<p>
When the function object is invoked with a first argument <b>x</b> that is
neither a pointer nor a reference to the appropriate class (<b>X</b> in the
example above), it uses <tt>get_pointer(x)</tt> to obtain a pointer from
<b>x</b>. Library authors can "register" their smart pointer classes by
supplying an appropriate <b>get_pointer</b> overload, allowing <b>mem_fn</b>
to recognize and support them.
</p>
<p>
A <b>get_pointer</b> overload for <b>boost::shared_ptr</b> is supplied.
</p>
<p>
[Note: <b>get_pointer</b> is not restricted to return a pointer. Any object
that can be used in a member function call expression <tt>(x->*pmf)(...)</tt>
will work.]
</p>
<p>
[Note: the library uses an unqualified call to <b>get_pointer</b>. Therefore,
it will find, through argument-dependent lookup, <b>get_pointer</b> overloads
that are defined in the same namespace as the corresponding smart pointer
class, in addition to any <b>boost::get_pointer</b> overloads.]
</p>
<p>
All function objects returned by <b>mem_fn</b> expose a <b>result_type</b>
typedef that represents the return type of the member function.
</p>
<h2>Interface</h2>
<h3>Synopsis</h3>
<pre>
namespace boost
{
template&lt;class T&gt; T * <a href="#get_pointer_1">get_pointer</a>(T * p);
template&lt;class T&gt; T * <a href="#get_pointer_2">get_pointer</a>(shared_ptr&lt;T&gt; const &amp; p);
template&lt;class R, class T&gt; <i>implementation-defined-1</i> <a href="#mem_fn_1">mem_fn</a>(R (T::*pmf) ());
template&lt;class R, class T&gt; <i>implementation-defined-2</i> <a href="#mem_fn_2">mem_fn</a>(R (T::*pmf) () const);
template&lt;class R, class T, class A1&gt; <i>implementation-defined-3</i> <a href="#mem_fn_3">mem_fn</a>(R (T::*pmf) (A1));
template&lt;class R, class T, class A1&gt; <i>implementation-defined-4</i> <a href="#mem_fn_4">mem_fn</a>(R (T::*pmf) (A1) const);
template&lt;class R, class T, class A1, class A2&gt; <i>implementation-defined-5</i> <a href="#mem_fn_5">mem_fn</a>(R (T::*pmf) (A1, A2));
template&lt;class R, class T, class A1, class A2&gt; <i>implementation-defined-6</i> <a href="#mem_fn_6">mem_fn</a>(R (T::*pmf) (A1, A2) const);
// implementation defined number of additional overloads for more arguments
}
</pre>
<h3>Common requirements</h3>
<p>
All <tt><i>implementation-defined-N</i></tt> types mentioned in the Synopsis are
<b>CopyConstructible</b> and <b>Assignable</b>.
Their copy constructors and assignment operators do not throw exceptions.
<tt><i>implementation-defined-N</i>::result_type</tt> is defined as
the return type of the member function pointer passed as an argument to <b>mem_fn</b>
(<b>R</b> in the Synopsis.)
</p>
<h3>get_pointer</h3>
<h4><a name="get_pointer_1">template&lt;class T&gt; T * get_pointer(T * p)</a></h4>
<p>
<b>Returns:</b> <tt>p</tt>.
</p>
<p>
<b>Throws:</b> Nothing.
</p>
<h4><a name="get_pointer_2">template&lt;class T&gt; T * get_pointer(shared_ptr&lt;T&gt; const &amp; p)</a></h4>
<p>
<b>Returns:</b> <tt>p.get()</tt>.
</p>
<p>
<b>Throws:</b> Nothing.
</p>
<h3>mem_fn</h3>
<h4><a name="mem_fn_1">template&lt;class R, class T&gt; <i>implementation-defined-1</i> mem_fn(R (T::*pmf) ())</a></h4>
<p>
<b>Returns:</b> a function object <i>f</i> such that the expression
<tt><i>f(t)</i></tt> is equivalent to <tt>(t.*pmf)()</tt> when <i>t</i>
is an l-value of type <b>T</b>, <tt>(get_pointer(t)->*pmf)()</tt> otherwise.
</p>
<p>
<b>Throws:</b> Nothing.
</p>
<h4><a name="mem_fn_2">template&lt;class R, class T&gt; <i>implementation-defined-2</i> mem_fn(R (T::*pmf) () const)</a></h4>
<p>
<b>Returns:</b> a function object <i>f</i> such that the expression
<tt><i>f(t)</i></tt> is equivalent to <tt>(t.*pmf)()</tt> when <i>t</i>
is of type <b>T <i>[</i>const<i>]</i></b>, <tt>(get_pointer(t)->*pmf)()</tt> otherwise.
</p>
<p>
<b>Throws:</b> Nothing.
</p>
<h4><a name="mem_fn_3">template&lt;class R, class T, class A1&gt; <i>implementation-defined-3</i> mem_fn(R (T::*pmf) (A1))</a></h4>
<p>
<b>Returns:</b> a function object <i>f</i> such that the expression
<tt><i>f(t, a1)</i></tt> is equivalent to <tt>(t.*pmf)(a1)</tt> when <i>t</i>
is an l-value of type <b>T</b>, <tt>(get_pointer(t)->*pmf)(a1)</tt> otherwise.
</p>
<p>
<b>Throws:</b> Nothing.
</p>
<h4><a name="mem_fn_4">template&lt;class R, class T, class A1&gt; <i>implementation-defined-4</i> mem_fn(R (T::*pmf) (A1) const)</a></h4>
<p>
<b>Returns:</b> a function object <i>f</i> such that the expression
<tt><i>f(t, a1)</i></tt> is equivalent to <tt>(t.*pmf)(a1)</tt> when <i>t</i>
is of type <b>T <i>[</i>const<i>]</i></b>, <tt>(get_pointer(t)->*pmf)(a1)</tt> otherwise.
</p>
<p>
<b>Throws:</b> Nothing.
</p>
<h4><a name="mem_fn_5">template&lt;class R, class T, class A1, class A2&gt; <i>implementation-defined-5</i> mem_fn(R (T::*pmf) (A1, A2))</a></h4>
<p>
<b>Returns:</b> a function object <i>f</i> such that the expression
<tt><i>f(t, a1, a2)</i></tt> is equivalent to <tt>(t.*pmf)(a1, a2)</tt> when <i>t</i>
is an l-value of type <b>T</b>, <tt>(get_pointer(t)->*pmf)(a1, a2)</tt> otherwise.
</p>
<p>
<b>Throws:</b> Nothing.
</p>
<h4><a name="mem_fn_6">template&lt;class R, class T, class A1, class A2&gt; <i>implementation-defined-6</i> mem_fn(R (T::*pmf) (A1, A2) const)</a></h4>
<p>
<b>Returns:</b> a function object <i>f</i> such that the expression
<tt><i>f(t, a1, a2)</i></tt> is equivalent to <tt>(t.*pmf)(a1, a2)</tt> when <i>t</i>
is of type <b>T <i>[</i>const<i>]</i></b>, <tt>(get_pointer(t)->*pmf)(a1, a2)</tt> otherwise.
</p>
<p>
<b>Throws:</b> Nothing.
</p>
<h2>Implementation</h2>
<p>
This implementation supports member functions with up to eight arguments.
This is not an inherent limitation of the design, but an implementation
detail.
</p>
<h2>Acknowledgements</h2>
<p>
Rene Jager's initial suggestion of using traits classes to make
<b>mem_fn</b> adapt to user-defined smart pointers inspired the
<b>get_pointer</b>-based design.
</p>
<p>
Numerous improvements were suggested during the formal review period by
Richard Crossley, Jens Maurer, Ed Brey, and others. Review manager
was Darin Adler.
</p>
<p><br><br><br><small>Copyright &copy; 2001 by Peter Dimov and Multi Media
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 &quot;as is&quot; without express or implied warranty, and with
no claim as to its suitability for any purpose.</small></p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>

175
mem_fn_test.cpp Normal file
View File

@@ -0,0 +1,175 @@
#if defined(_MSC_VER) && !defined(__ICL)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
//
// mem_fn_test.cpp - a test for mem_fn.hpp
//
// Version 1.02.0001 (2001-08-30)
//
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/mem_fn.hpp>
#include <boost/smart_ptr.hpp>
#include <iostream>
struct X
{
mutable unsigned int hash;
X(): hash(0) {}
int f0() { f1(17); return 0; }
int g0() const { g1(17); return 0; }
int f1(int a1) { hash = (hash * 17041 + a1) % 32768; return 0; }
int g1(int a1) const { hash = (hash * 17041 + a1 * 2) % 32768; return 0; }
int f2(int a1, int a2) { f1(a1); f1(a2); return 0; }
int g2(int a1, int a2) const { g1(a1); g1(a2); return 0; }
int f3(int a1, int a2, int a3) { f2(a1, a2); f1(a3); return 0; }
int g3(int a1, int a2, int a3) const { g2(a1, a2); g1(a3); return 0; }
int f4(int a1, int a2, int a3, int a4) { f3(a1, a2, a3); f1(a4); return 0; }
int g4(int a1, int a2, int a3, int a4) const { g3(a1, a2, a3); g1(a4); return 0; }
int f5(int a1, int a2, int a3, int a4, int a5) { f4(a1, a2, a3, a4); f1(a5); return 0; }
int g5(int a1, int a2, int a3, int a4, int a5) const { g4(a1, a2, a3, a4); g1(a5); return 0; }
int f6(int a1, int a2, int a3, int a4, int a5, int a6) { f5(a1, a2, a3, a4, a5); f1(a6); return 0; }
int g6(int a1, int a2, int a3, int a4, int a5, int a6) const { g5(a1, a2, a3, a4, a5); g1(a6); return 0; }
int f7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) { f6(a1, a2, a3, a4, a5, a6); f1(a7); return 0; }
int g7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) const { g6(a1, a2, a3, a4, a5, a6); g1(a7); return 0; }
int f8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { f7(a1, a2, a3, a4, a5, a6, a7); f1(a8); return 0; }
int g8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) const { g7(a1, a2, a3, a4, a5, a6, a7); g1(a8); return 0; }
};
int detect_errors(bool x)
{
if(x)
{
std::cerr << "no errors detected.\n";
return 0;
}
else
{
std::cerr << "test failed.\n";
return 1;
}
}
int main()
{
using boost::mem_fn;
X x;
X const & rcx = x;
X const * pcx = &x;
boost::shared_ptr<X> sp(new X);
mem_fn(&X::f0)(x);
mem_fn(&X::f0)(&x);
mem_fn(&X::f0)(sp);
mem_fn(&X::g0)(x);
mem_fn(&X::g0)(rcx);
mem_fn(&X::g0)(&x);
mem_fn(&X::g0)(pcx);
mem_fn(&X::g0)(sp);
mem_fn(&X::f1)(x, 1);
mem_fn(&X::f1)(&x, 1);
mem_fn(&X::f1)(sp, 1);
mem_fn(&X::g1)(x, 1);
mem_fn(&X::g1)(rcx, 1);
mem_fn(&X::g1)(&x, 1);
mem_fn(&X::g1)(pcx, 1);
mem_fn(&X::g1)(sp, 1);
mem_fn(&X::f2)(x, 1, 2);
mem_fn(&X::f2)(&x, 1, 2);
mem_fn(&X::f2)(sp, 1, 2);
mem_fn(&X::g2)(x, 1, 2);
mem_fn(&X::g2)(rcx, 1, 2);
mem_fn(&X::g2)(&x, 1, 2);
mem_fn(&X::g2)(pcx, 1, 2);
mem_fn(&X::g2)(sp, 1, 2);
mem_fn(&X::f3)(x, 1, 2, 3);
mem_fn(&X::f3)(&x, 1, 2, 3);
mem_fn(&X::f3)(sp, 1, 2, 3);
mem_fn(&X::g3)(x, 1, 2, 3);
mem_fn(&X::g3)(rcx, 1, 2, 3);
mem_fn(&X::g3)(&x, 1, 2, 3);
mem_fn(&X::g3)(pcx, 1, 2, 3);
mem_fn(&X::g3)(sp, 1, 2, 3);
mem_fn(&X::f4)(x, 1, 2, 3, 4);
mem_fn(&X::f4)(&x, 1, 2, 3, 4);
mem_fn(&X::f4)(sp, 1, 2, 3, 4);
mem_fn(&X::g4)(x, 1, 2, 3, 4);
mem_fn(&X::g4)(rcx, 1, 2, 3, 4);
mem_fn(&X::g4)(&x, 1, 2, 3, 4);
mem_fn(&X::g4)(pcx, 1, 2, 3, 4);
mem_fn(&X::g4)(sp, 1, 2, 3, 4);
mem_fn(&X::f5)(x, 1, 2, 3, 4, 5);
mem_fn(&X::f5)(&x, 1, 2, 3, 4, 5);
mem_fn(&X::f5)(sp, 1, 2, 3, 4, 5);
mem_fn(&X::g5)(x, 1, 2, 3, 4, 5);
mem_fn(&X::g5)(rcx, 1, 2, 3, 4, 5);
mem_fn(&X::g5)(&x, 1, 2, 3, 4, 5);
mem_fn(&X::g5)(pcx, 1, 2, 3, 4, 5);
mem_fn(&X::g5)(sp, 1, 2, 3, 4, 5);
mem_fn(&X::f6)(x, 1, 2, 3, 4, 5, 6);
mem_fn(&X::f6)(&x, 1, 2, 3, 4, 5, 6);
mem_fn(&X::f6)(sp, 1, 2, 3, 4, 5, 6);
mem_fn(&X::g6)(x, 1, 2, 3, 4, 5, 6);
mem_fn(&X::g6)(rcx, 1, 2, 3, 4, 5, 6);
mem_fn(&X::g6)(&x, 1, 2, 3, 4, 5, 6);
mem_fn(&X::g6)(pcx, 1, 2, 3, 4, 5, 6);
mem_fn(&X::g6)(sp, 1, 2, 3, 4, 5, 6);
mem_fn(&X::f7)(x, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::f7)(&x, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::f7)(sp, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::g7)(x, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::g7)(rcx, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::g7)(&x, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::g7)(pcx, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::g7)(sp, 1, 2, 3, 4, 5, 6, 7);
mem_fn(&X::f8)(x, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::f8)(&x, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::f8)(sp, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::g8)(x, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::g8)(rcx, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::g8)(&x, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::g8)(pcx, 1, 2, 3, 4, 5, 6, 7, 8);
mem_fn(&X::g8)(sp, 1, 2, 3, 4, 5, 6, 7, 8);
return detect_errors(x.hash == 17610 && sp->hash == 2155);
}