Compare commits

...

109 Commits

Author SHA1 Message Date
Peter Dimov
6513a8558a Merge branch 'develop' 2015-05-04 01:08:08 +03:00
Peter Dimov
0dbd9b908d Merge pull request #11 from K-ballo/fix-ambiguous-void
Fix for bind<void>(mf) ambiguous resolution error
2015-04-29 20:10:24 +03:00
K-ballo
150c4e94e3 Fix for bind<void>(mf) ambiguous resolution error 2015-04-29 13:33:53 -03:00
Peter Dimov
0aca000b8f Merge branch 'develop' 2015-03-22 18:02:12 +02:00
Peter Dimov
42b5cef177 Better argument forwarding when rvalue references are available. 2015-03-20 18:16:44 +02:00
Peter Dimov
8e54850ab6 Add forwarding test for 2 arguments. 2015-03-20 16:53:30 +02:00
Peter Dimov
46c414606c Add forwarding test. 2015-03-20 16:43:54 +02:00
Peter Dimov
b4881265fb Add test for a function+bind regression reported by Marcel Raad 2015-03-20 16:32:43 +02:00
Peter Dimov
6f2879927d Merge branch 'develop' 2015-01-25 22:21:42 +02:00
Peter Dimov
1a6c2ffff3 Ignore generated documentation. 2015-01-25 22:21:11 +02:00
Peter Dimov
e9f6ccde39 Merge branch 'develop' 2015-01-25 18:27:56 +02:00
Peter Dimov
6ac4bef225 Fix error in example. 2015-01-22 21:48:54 +02:00
Peter Dimov
b2eb0a4ae8 Add acknowledgment. 2015-01-22 21:46:33 +02:00
Peter Dimov
32060bf523 Merge branch 'feature/quickbook-documentation' into develop 2015-01-22 21:39:24 +02:00
Peter Dimov
42069e5103 Merge branch 'boostbook' of https://github.com/K-ballo/bind into feature/quickbook-documentation 2015-01-22 21:18:04 +02:00
Peter Dimov
7eac98452a Merge branch 'void' of https://github.com/K-ballo/bind into develop 2015-01-22 21:06:39 +02:00
K-ballo
360ac7c2b4 Added doc redirect pages in the root directory 2014-08-21 18:15:00 -03:00
K-ballo
fa5c928e88 Ported mem_fn documentation to BoostBook 2014-08-21 18:03:21 -03:00
Peter Dimov
1feb7dc796 Merge branch 'develop' 2014-08-21 23:58:41 +03:00
Peter Dimov
ea54c3875d Merge pull request #8 from danieljames/metadata
Create metadata file.
2014-08-21 23:55:38 +03:00
Peter Dimov
b8e4c378b1 Merge branch 'develop' 2014-08-21 23:49:39 +03:00
K-ballo
f199894060 Ported bind documentation to BoostBook 2014-08-21 17:49:23 -03:00
Daniel James
53ff21f0f8 Remove ref from metadata.
It's now in core.
2014-08-21 20:34:34 +01:00
K-ballo
30921a3889 Completed support for bind<void> 2014-08-21 16:27:27 -03:00
K-ballo
c89afa6aaa Added test case for existing bind<void> support. 2014-08-21 14:43:40 -03:00
Peter Dimov
f91369d163 Update links to ref.html. 2014-08-21 14:24:05 +03:00
Peter Dimov
33a19056dc Delete ref documentation; it's now in core. 2014-08-21 14:12:08 +03:00
Peter Dimov
41d7508139 Merge branch 'develop' 2014-08-21 13:23:22 +03:00
Peter Dimov
89d3d468b1 Merge pull request #7 from jzmaddock/patch-2
Update Jamfile.v2
2014-08-21 13:22:20 +03:00
Daniel James
29b1a0d6b9 Add metadata file. 2014-08-18 15:49:05 +01:00
jzmaddock
f769d97362 Update Jamfile.v2
There can only be one project called "boost/doc" and this isn't it ;-)

So the patch changes the name to something else.
2014-08-11 18:26:54 +01:00
Peter Dimov
1480db5679 Merge branch 'develop' 2014-02-05 05:22:20 +02:00
Peter Dimov
f53694ef25 Merge branch 'develop' of https://github.com/boostorg/bind into develop 2013-12-18 19:04:20 +02:00
Peter Dimov
0afd49b884 Merge pull request #3 from danieljames/develop
Link to compose in old version of boost.
2013-12-16 15:03:04 -08:00
Daniel James
dd67e3f785 Link to compose from old version of boost.
Compose isn't included in modular boost, so there's nothing to link to.
I changed it to link to an old version which still has compose
documentation. It might be better to rewrite it?
2013-12-15 17:27:54 +00:00
Peter Dimov
c92a49d5c2 Merge commit 'f7e101e928c745199436374f944f0438b97dee28' into develop 2013-12-12 02:57:54 +02:00
Peter Dimov
a6b17d9001 Switch to BOOST_STATIC_ASSERT in arg.hpp per the patch in #8844. 2013-12-12 00:12:56 +02:00
Peter Dimov
ea05f23163 Fixed mem_fn_eq_test to work with /OPT:ICF as per the patch in #8734 by Mike Liang. 2013-12-11 23:58:19 +02:00
Peter Dimov
fafb6bb650 Merge branch 'topic/silence_warning' of https://github.com/timblechmann/bind into develop 2013-12-07 19:10:42 +02:00
Peter Dimov
f7e101e928 Merge branch 'develop' 2013-12-07 19:05:57 +02:00
Peter Dimov
166c4b6be7 Merge from master to create a merge point. 2013-12-07 19:03:34 +02:00
Peter Dimov
8414233b9c Revert "Bind: Remove obsolete MSVC version check"
This reverts commit 9955139c65.
2013-12-07 18:54:00 +02:00
Peter Dimov
15d6d6ac95 Revert "Remove obsolete MSVC check from pragma guard"
This reverts commit 5e2fc717f0.
2013-12-07 18:53:27 +02:00
Peter Dimov
ba117db120 Revert "Bind: Remove obsolete GCC version check."
This reverts commit 5b2cf44de5.
2013-12-07 18:53:01 +02:00
Peter Dimov
f5c95610b6 Revert "Remove BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION"
This reverts commit af136e483d.
2013-12-07 18:52:39 +02:00
Peter Dimov
ce0fc0f69a Revert "Simplify multi-component ifdefs containing BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION"
This reverts commit 0f66412487.
2013-12-07 18:51:53 +02:00
Peter Dimov
aa8a94273d Revert "Remove remaining occurances of BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION"
This reverts commit 7ff6524bd1.
2013-12-07 18:50:56 +02:00
Tim Blechmann
92ff08b873 bind: silence warning with gcc 2013-12-07 14:37:28 +01:00
Michel Morin
6315df35d6 Merge r86524 (Correct broken links to C++ standard papers); fixes #9212
[SVN r86673]
2013-11-13 03:22:55 +00:00
Michel Morin
96fd1e7036 Correct broken links to C++ standard papers. Refs #9212.
[SVN r86524]
2013-10-30 12:51:24 +00:00
Stephen Kelly
7ff6524bd1 Remove remaining occurances of BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
These evaded scripting.

[SVN r86249]
2013-10-11 23:22:36 +00:00
Stephen Kelly
0f66412487 Simplify multi-component ifdefs containing BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
[SVN r86248]
2013-10-11 23:20:59 +00:00
Stephen Kelly
af136e483d Remove BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
Process #ifndef...#endif conditions.

[SVN r86244]
2013-10-11 23:15:00 +00:00
Stephen Kelly
5b2cf44de5 Bind: Remove obsolete GCC version check.
[SVN r86106]
2013-10-01 08:42:35 +00:00
Stephen Kelly
5e2fc717f0 Remove obsolete MSVC check from pragma guard
git grep -h -B1 "^#\s*pragma once" | grep -v pragma | sort | uniq

is now clean.

[SVN r85952]
2013-09-26 13:02:51 +00:00
Stephen Kelly
9955139c65 Bind: Remove obsolete MSVC version check
[SVN r85938]
2013-09-26 09:42:51 +00:00
Peter Dimov
fa8debfc80 Merge [75391] to release. Fixes #5792.
[SVN r75755]
2011-11-30 17:53:38 +00:00
Peter Dimov
da3580cc14 Apply suggested IBM C++ fix. Refs #5792.
[SVN r75391]
2011-11-07 18:25:33 +00:00
Bryce Adelstein-Lelbach
27003baf12 Pathscale-4.0 configuration code/workarounds.
[SVN r68142]
2011-01-14 02:59:34 +00:00
Marshall Clow
c53ba15ce5 Merge doc fix to release; fixes #4532
[SVN r67047]
2010-12-05 22:18:05 +00:00
Marshall Clow
3d60d74ff0 Doc patch; refs #4532
[SVN r66973]
2010-12-02 13:17:09 +00:00
Peter Dimov
7b89dd7fd9 Merge [62251] to release. Fixes #4172.
[SVN r63828]
2010-07-10 21:26:25 +00:00
Daniel James
787d3cb7b4 Merge documentation fixes.
* Use `doc/src/*.css` instead of `doc/html/*.css`.
* Remove wiki and people directories.
* Some documentation fixes.
* Left out `minimal.css` changes and boostbook changes because of clashes.


[SVN r63347]
2010-06-26 12:30:09 +00:00
Daniel James
f89c41dc7b Update various libraries' documentation build.
Mostly to use the images and css files under doc/src instead of
doc/html, usually be deleting the settings in order to use the defaults.
Also add 'boost.root' to some builds in order to fix links which rely on
it.

[SVN r63146]
2010-06-20 18:00:48 +00:00
Peter Dimov
7aa58cf653 Fix version check, as g++ 4.1 still has the PCH bug. Refs #4172.
[SVN r62251]
2010-05-26 19:34:10 +00:00
Peter Dimov
1bf8cd6c7a Fix Borland regression. Refs #3003.
[SVN r58093]
2009-12-02 10:47:01 +00:00
Peter Dimov
e5d99ce085 Make mem_fn work with overloaded unary operator&. Refs #3003. Sorry it took so long.
[SVN r58073]
2009-12-01 02:24:53 +00:00
Peter Dimov
17282c97c2 Extend Borland workaround to 6.2 and above.
[SVN r57954]
2009-11-26 21:02:04 +00:00
John Maddock
f02b090fe8 Warning suppressions in Boost.Bind.
Fixes #3601.

[SVN r57542]
2009-11-10 13:26:43 +00:00
Troy D. Straszheim
f3da835e0b rm cmake from trunk. I'm not entirely sure this is necessary to satisfy the inspect script, but I'm not taking any chances, and it is easy to put back
[SVN r56942]
2009-10-17 02:07:38 +00:00
Troy D. Straszheim
73fc778b61 Copyrights on CMakeLists.txt to keep them from clogging up the inspect
reports.  This is essentially the same commit as r55095 on the release
branch.



[SVN r55159]
2009-07-26 00:49:56 +00:00
Steven Watanabe
26ee2825fe Make protect use the same approximation of perfect forwarding as plain bind.
[SVN r54385]
2009-06-26 22:31:15 +00:00
Frank Mori Hess
dc1e4dbfae Use static boost::arg placeholders for gcc 4.0.1, since it has
a bug that prevents forwarding placeholders as const references
when using the static inline function placeholders.


[SVN r52384]
2009-04-14 13:45:59 +00:00
Peter Dimov
45a1f1434b Add ref_compare for weak_ptr. Refs #2849.
[SVN r51979]
2009-03-26 00:43:14 +00:00
Peter Dimov
bc50ab0ba3 Refs #2128 (fixed in trunk.)
[SVN r51512]
2009-03-01 17:04:14 +00:00
Peter Dimov
010349ec9b Refs #2127 (fixed in trunk).
[SVN r51511]
2009-03-01 16:31:53 +00:00
Peter Dimov
8ae9e8460d Borland 6.10 still needs the workaround; fails bind_dm_test without it.
[SVN r51510]
2009-03-01 16:06:44 +00:00
Peter Dimov
5d49fb45d0 Make bind.hpp and mem_fn.hpp forward to bind/bind.hpp and bind/mem_fn.hpp. (Ref #2238)
[SVN r51489]
2009-02-28 21:40:27 +00:00
Peter Dimov
4000680b6a Copy mem_fn.hpp to bind/
[SVN r51488]
2009-02-28 21:27:51 +00:00
Peter Dimov
851903fcc4 Copy bind.hpp into bind/
[SVN r51487]
2009-02-28 21:26:59 +00:00
John Maddock
1d79533df7 Add PDF generation options to fix external links to point to the web site.
Added a few more Boostbook based libs that were missed first time around.
Fixed PDF naming issues.

[SVN r51284]
2009-02-17 10:05:58 +00:00
Michael A. Jackson
f09a7a5747 Updating dependency information for modularized libraries.
[SVN r49628]
2008-11-07 17:05:27 +00:00
Michael A. Jackson
0b72bfbd9b Updating CMake files to latest trunk. Added dependency information for regression tests and a few new macros for internal use.
[SVN r49627]
2008-11-07 17:02:56 +00:00
Michael A. Jackson
61519fcae2 Continuing merge of CMake build system files into trunk with the encouragement of Doug Gregor
[SVN r49510]
2008-11-01 13:15:41 +00:00
Peter Dimov
48c5a6e682 Fix #2245.
[SVN r48840]
2008-09-17 23:07:33 +00:00
Ronald Garcia
1b292ee487 For building the ref docs stand-alone.
[SVN r47690]
2008-07-22 14:58:14 +00:00
Ronald Garcia
0dd5dae4e8 Added documentation for unwrap_ref.
[SVN r47689]
2008-07-22 14:55:05 +00:00
Peter Dimov
203ca82ef2 bind( type<R>(), f, ... ) now works when f is a member function.
[SVN r45619]
2008-05-21 19:49:47 +00:00
Peter Dimov
037a4d1976 Add ref_fn_test.cpp per #1846.
[SVN r44704]
2008-04-21 21:29:28 +00:00
Peter Dimov
dfd3da2cc4 Fix #1643.
[SVN r43323]
2008-02-19 15:40:58 +00:00
Peter Dimov
aef08dd0cd Fix #1642.
[SVN r43321]
2008-02-19 15:09:10 +00:00
Peter Dimov
ef993c777a Fix #1646.
[SVN r43320]
2008-02-19 14:59:28 +00:00
Peter Dimov
f58543ac11 Fix #1641.
[SVN r43319]
2008-02-19 14:51:10 +00:00
Peter Dimov
f1afd17717 Added support for &&, ||
[SVN r43269]
2008-02-15 18:40:36 +00:00
Markus Schöpflin
e73f08edee Modified spelling of my surname to avoid problems with non-ASCII characters.
[SVN r42436]
2008-01-03 10:04:39 +00:00
Vladimir Prus
3c24cbedf6 Remove V1 Jamfiles
[SVN r38516]
2007-08-08 19:02:26 +00:00
Peter Dimov
79f8680eda Fix #997
[SVN r38165]
2007-07-07 17:41:54 +00:00
Peter Dimov
e163aeb563 Use object placeholders for g++ 4.1+, reported and PCH-tested by Daniel Walker
[SVN r38164]
2007-07-07 17:22:26 +00:00
Peter Dimov
ce24d4f735 Fixed to compile
[SVN r37357]
2007-04-04 21:30:32 +00:00
Peter Dimov
41d9fbc317 License update
[SVN r35988]
2006-11-10 18:27:05 +00:00
Peter Dimov
2f595f53f5 License/copyright edits
[SVN r35954]
2006-11-09 19:29:42 +00:00
Beman Dawes
c746cf26de Add copyright, license
[SVN r35905]
2006-11-07 19:11:57 +00:00
Peter Dimov
a695360c4f Borland fix
[SVN r35661]
2006-10-18 17:36:50 +00:00
Peter Dimov
0aadd1805d Rvalue overloads (suggested by Herve Bronnimann)
[SVN r35640]
2006-10-16 19:11:29 +00:00
Douglas Gregor
0cc198acc2 Work around ADL bug in GCC 3.3 that is causing failures in the Signals library
[SVN r35224]
2006-09-20 13:07:20 +00:00
Peter Dimov
b272145f3e Moved the specialization into namespace boost
[SVN r34477]
2006-07-07 19:09:16 +00:00
Peter Dimov
bfe10df38a is_placeholder, is_bind_expression added.
[SVN r34468]
2006-07-06 13:47:26 +00:00
Peter Dimov
c69a4ad382 Fixed a visit_each-related bug exposed by strict two-phase lookup
[SVN r33761]
2006-04-21 13:14:58 +00:00
Peter Dimov
683d699e4a Added diagnostic output.
[SVN r33754]
2006-04-21 11:55:39 +00:00
37 changed files with 3146 additions and 1291 deletions

978
bind.html
View File

@@ -1,954 +1,28 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!DOCTYPE html>
<html>
<head>
<title>Boost: bind.hpp documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%" bgColor="white">
<table width="100%" border="0">
<tr>
<td width="277"><A href="../../index.htm"><IMG height="86" alt="boost.png (6897 bytes)" src="../../boost.png" width="277" border="0"></A>
</td>
<td align="center">
<h1>bind.hpp</h1>
</td>
</tr>
<tr>
<td colSpan="2" height="64">&nbsp;</td>
</tr>
</table>
<h2>Contents</h2>
<h3 style="MARGIN-LEFT: 20pt"><A href="#Purpose">Purpose</A></h3>
<h4 style="MARGIN-LEFT: 40pt"><A href="#with_functions">Using bind with functions and
function pointers</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#with_function_objects">Using bind with function
objects</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#with_member_pointers">Using bind with pointers
to members</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#nested_binds">Using nested binds for function
composition</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#operators">Overloaded operators</A></h4>
<h3 style="MARGIN-LEFT: 20pt"><A href="#Examples">Examples</A></h3>
<h4 style="MARGIN-LEFT: 40pt"><A href="#with_algorithms">Using bind with standard
algorithms</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#with_boost_function">Using bind with
Boost.Function</A></h4>
<h3 style="MARGIN-LEFT: 20pt"><A href="#Limitations">Limitations</A></h3>
<h3 style="MARGIN-LEFT: 20pt"><A href="#FAQ">Frequently Asked Questions</A></h3>
<h4 style="MARGIN-LEFT: 40pt"><A href="#Q_doesnt_compile">Why doesn't this compile?</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#Q_does_compile">Why does this compile? It
should not.</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#Q_forms">What is the difference between bind(f,
...) and bind&lt;R&gt;(f, ...)?</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#Q_win32_api">Does <b>bind</b> work with Windows
API functions?</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#Q_com">Does <b>bind</b> work with COM methods?</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#Q_mac">Does <b>bind</b> work with Mac toolbox
functions?</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#Q_extern_C">Does <b>bind</b> work with extern
"C" functions?</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#Q_auto_stdcall">Why doesn't <b>bind</b> automatically
recognize nonstandard functions?</A></h4>
<h3 style="MARGIN-LEFT: 20pt"><A href="#Troubleshooting">Troubleshooting</A></h3>
<h4 style="MARGIN-LEFT: 40pt"><A href="#err_num_args">Incorrect number of arguments</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#err_signature">The function object cannot be
called with the specified arguments</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#err_arg_access">Accessing an argument that does
not exist</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#err_short_form">Inappropriate use of bind(f,
...)</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#err_long_form">Inappropriate use of
bind&lt;R&gt;(f, ...)</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#err_nonstd">Binding a nonstandard function</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#err_overloaded">Binding an overloaded function</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#err_const_arg"><b>const</b> in signatures</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#err_msvc_using">MSVC specific: using
boost::bind;</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#err_msvc_class_template">MSVC specific: class
templates shadow function templates</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#err_msvc_ellipsis">MSVC specific: ... in
signatures treated as type</A></h4>
<h3 style="MARGIN-LEFT: 20pt"><A href="#Interface">Interface</A></h3>
<h4 style="MARGIN-LEFT: 40pt"><A href="#Synopsis">Synopsis</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#CommonRequirements">Common requirements</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#CommonDefinitions">Common definitions</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#bind">bind</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#AdditionalOverloads">Additional overloads</A></h4>
<h3 style="MARGIN-LEFT: 20pt"><A href="#Implementation">Implementation</A></h3>
<h4 style="MARGIN-LEFT: 40pt"><A href="#Files">Files</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#Dependencies">Dependencies</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#NumberOfArguments">Number of Arguments</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#stdcall">"__stdcall", "__cdecl", "__fastcall",
and "pascal" Support</A></h4>
<h4 style="MARGIN-LEFT: 40pt"><A href="#visit_each"><b>visit_each</b> support</A></h4>
<h3 style="MARGIN-LEFT: 20pt"><A href="#Acknowledgements">Acknowledgements</A></h3>
<h2><a name="Purpose">Purpose</a></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><a name="with_functions">Using bind with functions and function pointers</a></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::bind2nd(std::ptr_fun(f), 5)(x);
</pre>
<p><b>bind</b> covers the functionality of <b>std::bind1st</b> as well:
</p>
<pre>std::bind1st(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>Note that, in the last example, the function object produced by <tt>bind(g, _1, _1,
_1)</tt> does not contain references to any arguments beyond the first, but
it can still be used with more than one argument. Any extra arguments are
silently ignored, just like the first and the second argument are ignored in
the third example.
</p>
<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);
bind(f, cref(42), _1);
</pre>
<h3><a name="with_function_objects">Using bind with function objects</a></h3>
<p><b>bind</b> is not limited to functions; it accepts arbitrary function objects.
In the general case, 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):
</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>Some compilers have trouble with the <tt>bind&lt;R&gt;(f, ...)</tt> syntax. For
portability reasons, an alternative way to express the above is supported:</p>
<pre>boost::bind(boost::type&lt;int&gt;(), f, _1, _1)(x);
</pre>
<P>Note, however, that the alternative syntax is provided only as a workaround. It
is not part of the interface.</P>
<P>When the function object exposes a nested type named <b>result_type</b>, the
explicit return type can be omitted:
</P>
<pre>int x = 8;
bind(std::less&lt;int&gt;(), _1, 9)(x); // x &lt; 9
</pre>
<p>[Note: the ability to omit the return type is not available on all compilers.]
</p>
<P>By default, <STRONG>bind</STRONG> makes a copy of the provided function object. <code>
boost::ref</code> and <code>boost::cref</code> can be used to make it store
a reference to the function object, rather than a copy. This can be useful when
the function object is noncopyable, expensive to copy, or contains state; of
course, in this case the programmer is expected to ensure that the function
object is not destroyed while it's still being used.</P>
<pre>struct F2
{
int s;
typedef void result_type;
void operator()( int x ) { s += x; }
};
F2 f2 = { 0 };
int a[] = { 1, 2, 3 };
std::for_each( a, a+3, bind( ref(f2), _1 ) );
assert( f2.s == 6 );
</pre>
<h3><a name="with_member_pointers">Using bind with pointers to members</a></h3>
<p>Pointers to member functions and pointers to data members are not function
objects, because they do not support <tt>operator()</tt>. For convenience, <b>bind</b>
accepts member 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 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> (for member functions) or the
type of the member (for data members.)
</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, &amp;x, _1)(i); //(&amp;x)-&gt;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>)-&gt;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><a name="nested_binds">Using nested binds for function composition</a></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 inner <STRONG>bind</STRONG> expressions are evaluated, in unspecified order,
before the outer <STRONG>bind</STRONG> when the function object is called; the
results of the evaluation are then substituted in their place when the outer <STRONG>
bind</STRONG> is evaluated. In the example above, when the function object
is called with the argument list <tt>(x)</tt>, <tt>bind(g, _1)(x)</tt> is
evaluated first, yielding <tt>g(x)</tt>, and then <tt>bind(f, g(x))(x)</tt> is
evaluated, yielding the final result <tt>f(g(x))</tt>.
</p>
<P>This feature of <b>bind</b> can be used to perform function composition. 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 first argument - the bound function object - is not evaluated,
even when it's a function object that is produced by <STRONG>bind</STRONG> or a
placeholder argument, so the example below does not work as expected:
</p>
<pre>typedef void (*pf)(int);
std::vector&lt;pf&gt; v;
std::for_each(v.begin(), v.end(), bind(_1, 5));
</pre>
<p>The desired effect can be achieved via a helper function object <STRONG>apply</STRONG>
that applies its first argument, as a function object, to the rest of its
argument list. For convenience, an implementation of <STRONG>apply</STRONG> is
provided in the <STRONG>boost/bind/apply.hpp</STRONG> header file. Here is how
the modified version of the previous example looks like:
</p>
<pre>typedef void (*pf)(int);
std::vector&lt;pf&gt; v;
std::for_each(v.begin(), v.end(), bind(apply&lt;void&gt;(), _1, 5));
</pre>
<P>Although the first argument is, by default, not evaluated, all other arguments
are. Sometimes it is necessary not to evaluate arguments subsequent to the
first, even when they are nested <STRONG>bind</STRONG> subexpressions. This can
be achieved with the help of another function object, <STRONG>protect</STRONG>,
that masks the type so that <STRONG>bind</STRONG> does not recognize and
evaluate it. When called, <STRONG>protect</STRONG> simply forwards the argument
list to the other function object unmodified.</P>
<P>The header <STRONG>boost/bind/protect.hpp</STRONG> contains an implementation of <STRONG>
protect</STRONG>. To protect a <STRONG>bind</STRONG> function object from
evaluation, use <tt>protect(bind(f, ...))</tt>.</P>
<h3><a name="operators">Overloaded operators</a> (new in Boost 1.33)</h3>
<p>For convenience, the function objects produced by <tt>bind</tt> overload the
logical not operator <code>!</code> and the relational and logical operators <code>==</code>,
<code>!=</code>, <code>&lt;</code>, <code>&lt;=</code>, <code>&gt;</code>, <code>&gt;=</code>,
<code>&amp;&amp;</code>, <code>||</code>.</p>
<P><tt>!bind(f, ...)</tt> is equivalent to <tt>bind( <EM>logical_not</EM>(), bind(f,
...) )</tt>, where <tt><EM>logical_not</EM></tt> is a function object that
takes one argument <tt>x</tt> and returns <tt>!x</tt>.</P>
<P><tt>bind(f, ...) <EM>op</EM> x</tt>, where <EM>op</EM> is a relational or
logical operator, is equivalent to <tt>bind( <EM>relation</EM>(), bind(f, ...), x )</tt>,
where <em>relation</em> is a function object that takes two arguments <tt>a</tt>
and <tt>b</tt> and returns <tt>a <EM>op</EM> b</tt>.</P>
<P>What this means in practice is that you can conveniently negate the result of <tt>bind</tt>:</P>
<P><tt>std::remove_if( first, last, !bind( &amp;X::visible, _1 ) ); // remove invisible
objects</tt></P>
<P>and compare the result of <tt>bind</tt> against a value:</P>
<P><tt>std::find_if( first, last, bind( &amp;X::name, _1 ) == "Peter" );</tt></P>
<P><tt>std::find_if( first, last, bind( &amp;X::name, _1 ) == "Peter" || bind(
&amp;X::name, _1 ) == "Paul" );</tt></P>
<P>against a placeholder:</P>
<P><tt>bind( &amp;X::name, _1 ) == _2</tt></P>
<P>or against another <tt>bind</tt> expression:</P>
<P><tt>std::sort( first, last, bind( &amp;X::name, _1 ) &lt; bind( &amp;X::name, _2 )
); // sort by name</tt></P>
<h2><a name="Examples">Examples</a></h2>
<h3><a name="with_algorithms">Using bind with standard algorithms</a></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><a name="with_boost_function">Using bind with Boost.Function</a></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>
<h2><a name="Limitations">Limitations</a></h2>
<p>As a general rule, 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 in its
current (2003) incarnation, known as <A href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm">
the forwarding problem</A>. (It will be fixed in the next standard, usually
called C++0x.)</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>On compilers that support partial ordering of function templates, a possible
solution 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 requires providing 512 overloads for nine arguments, which
is impractical. The library chooses a small subset: for up to two arguments, it
provides the const overloads in full, for arities of three and more it provides
a single additional overload with all of the arguments taken by const
reference. This covers a reasonable portion of the use cases.
</p>
<h2><a name="FAQ">Frequently Asked Questions</a></h2>
<h3><a name="Q_doesnt_compile">Why doesn't this compile?</a></h3>
<p>See the <A href="#Troubleshooting">dedicated Troubleshooting section</A>.</p>
<h3><a name="Q_does_compile">Why does this compile? It should not.</a></h3>
<p>Probably because you used the general <tt>bind&lt;R&gt;(f, ...)</tt> syntax,
thereby instructing <b>bind</b> to not "inspect" <b>f</b> to detect arity and
return type errors.</p>
<h3><a name="Q_forms">What is the difference between bind(f, ...) and bind&lt;R&gt;(f,
...)?</a></h3>
<p>The first form instructs <b>bind</b> to inspect the type of <b>f</b> in order to
determine its arity (number of arguments) and return type. Arity errors will be
detected at "bind time". This syntax, of course, places some requirements on <b>f</b>.
It must be a function, function pointer, member function pointer, or a function
object that defines a nested type named <b>result_type</b>; in short, it must
be something that <b>bind</b> can recognize.</p>
<p>The second form instructs <b>bind</b> to <b>not</b> attempt to recognize the
type of <b>f</b>. It is generally used with function objects that do not, or
cannot, expose <b>result_type</b>, but it can also be used with nonstandard
functions. For example, the current implementation does not automatically
recognize variable-argument functions like <b>printf</b>, so you will have to
use <tt>bind&lt;int&gt;(printf, ...)</tt>. Note that an alternative <tt>bind(type&lt;R&gt;(),
f, ...)</tt> syntax is supported for portability reasons.</p>
<p>Another important factor to consider is that compilers without partial template
specialization or function template partial ordering support cannot handle the
first form when <b>f</b> is a function object, and in most cases will not
handle the second form when <b>f</b> is a function (pointer) or a member
function pointer.</p>
<h3><a name="Q_win32_api">Does <b>bind</b> work with Windows API functions?</a></h3>
<p>Yes, if you <A href="#stdcall">#define BOOST_BIND_ENABLE_STDCALL</A>. An
alternative is to treat the function as a <A href="#with_function_objects">generic
function object</A> and use the <tt>bind&lt;R&gt;(f, ...)</tt> syntax.</p>
<h3><a name="Q_com">Does <b>bind</b> work with COM methods?</a></h3>
<p>Yes, if you <A href="#stdcall">#define BOOST_MEM_FN_ENABLE_STDCALL</A>.</p>
<h3><a name="Q_mac">Does <b>bind</b> work with Mac toolbox functions?</a></h3>
<p>Yes, if you <A href="#stdcall">#define BOOST_BIND_ENABLE_PASCAL</A>. An
alternative is to treat the function as a <A href="#with_function_objects">generic
function object</A> and use the <tt>bind&lt;R&gt;(f, ...)</tt> syntax.</p>
<h3><a name="Q_extern_C">Does <b>bind</b> work with extern "C" functions?</a></h3>
<p>Sometimes. On some platforms, pointers to extern "C" functions are equivalent to
"ordinary" function pointers, so they work fine. Other platforms treat them as
different types. A platform-specific implementation of <b>bind</b> is expected
to handle the problem transparently; this implementation does not. As usual,
the workaround is to treat the function as a <A href="#with_function_objects">generic
function object</A> and use the <tt>bind&lt;R&gt;(f, ...)</tt> syntax.</p>
<h3><a name="Q_auto_stdcall">Why doesn't <b>bind</b> automatically recognize
nonstandard functions?</a></h3>
<p>Non-portable extensions, in general, should default to off to prevent vendor
lock-in. Had the <A href="#stdcall">appropriate macros</A> been defined
automatically, you could have accidentally taken advantage of them without
realizing that your code is, perhaps, no longer portable. In addition, some
compilers have the option to make <b>__stdcall</b> (<STRONG>__fastcall</STRONG>)
their default calling convention, in which case no separate support would be
necessary.</p>
<h2><a name="Troubleshooting">Troubleshooting</a></h2>
<h3><a name="err_num_args">Incorrect number of arguments</a></h3>
<p>In a <tt>bind(f, a1, a2, ..., aN)</tt> expression, the function object <b>f</b> must
be able to take exactly <b>N</b> arguments. This error is normally detected at
"bind time"; in other words, the compilation error is reported on the line
where bind() is invoked:</p>
<pre>int f(int, int);
int main()
{
boost::bind(f, 1); // error, f takes two arguments
boost::bind(f, 1, 2); // OK
}
</pre>
<p>A common variation of this error is to forget that member functions have an
implicit "this" argument:</p>
<pre>struct X
{
int f(int);
}
int main()
{
boost::bind(&amp;X::f, 1); // error, X::f takes two arguments
boost::bind(&amp;X::f, <b>_1</b>, 1); // OK
}
</pre>
<h3><a name="err_signature">The function object cannot be called with the specified
arguments</a></h3>
<p>As in normal function calls, the function object that is bound must be
compatible with the argument list. The incompatibility will usually be detected
by the compiler at "call time" and the result is typically an error in <b>bind.hpp</b>
on a line that looks like:</p>
<pre> return f(a[a1_], a[a2_]);
</pre>
<p>An example of this kind of error:</p>
<pre>int f(int);
int main()
{
boost::bind(f, "incompatible"); // OK so far, no call
boost::bind(f, "incompatible")(); // error, "incompatible" is not an int
boost::bind(f, _1); // OK
boost::bind(f, _1)("incompatible"); // error, "incompatible" is not an int
}
</pre>
<h3><a name="err_arg_access">Accessing an argument that does not exist</a></h3>
<p>The placeholder <b>_N</b> selects the argument at position <b>N</b> from the
argument list passed at "call time." Naturally, it is an error to attempt to
access beyond the end of this list:</p>
<pre>int f(int);
int main()
{
boost::bind(f, _1); // OK
boost::bind(f, _1)(); // error, there is no argument number 1
}
</pre>
<p>The error is usually reported in <b>bind.hpp</b>, at a line similar to:</p>
<pre> return f(a[a1_]);
</pre>
<p>When emulating <tt>std::bind1st(f, a)</tt>, a common mistake of this category is
to type <tt>bind(f, a, _2)</tt> instead of the correct <tt>bind(f, a, _1)</tt>.</p>
<h3><a name="err_short_form">Inappropriate use of bind(f, ...)</a></h3>
<p>The <tt>bind(f, a1, a2, ..., aN)</tt> <A href="#Q_forms">form</A> causes
automatic recognition of the type of <b>f</b>. It will not work with arbitrary
function objects; <b>f</b> must be a function or a member function pointer.</p>
<p>It is possible to use this form with function objects that define <b>result_type</b>,
but <b>only on compilers</b> that support partial specialization and partial
ordering. In particular, MSVC up to version 7.0 does not support this syntax
for function objects.</p>
<h3><a name="err_long_form">Inappropriate use of bind&lt;R&gt;(f, ...)</a></h3>
<p>The <tt>bind&lt;R&gt;(f, a1, a2, ..., aN)</tt> <A href="#Q_forms">form</A> supports
arbitrary function objects.</p>
<p>It is possible (but not recommended) to use this form with functions or member
function pointers, but <b>only on compilers</b> that support partial ordering.
In particular, MSVC up to version 7.0 does not fully support this syntax for
functions and member function pointers.</p>
<h3><a name="err_nonstd">Binding a nonstandard function</a></h3>
<p>By default, the <tt>bind(f, a1, a2, ..., aN)</tt> <A href="#Q_forms">form</A> recognizes
"ordinary" C++ functions and function pointers. <A href="#stdcall">Functions that
use a different calling convention</A>, or variable-argument functions such
as <STRONG>std::printf</STRONG>, do not work. The general <tt>bind&lt;R&gt;(f, a1,
a2, ..., aN)</tt> <A href="#Q_forms">form</A> works with nonstandard
functions.
</p>
<p>On some platforms, extern "C" functions, like <b>std::strcmp</b>, are not
recognized by the short form of bind.
</p>
<P>See also <A href="#stdcall">"__stdcall" and "pascal" Support</A>.</P>
<h3><a name="err_overloaded">Binding an overloaded function</a></h3>
<p>An attempt to bind an overloaded function usually results in an error, as there
is no way to tell which overload was meant to be bound. This is a common
problem with member functions with two overloads, const and non-const, as in
this simplified example:</p>
<pre>struct X
{
int&amp; get();
int const&amp; get() const;
};
int main()
{
boost::bind( &amp;X::get, _1 );
}
</pre>
<P>The ambiguity can be resolved manually by casting the (member) function pointer
to the desired type:</P>
<pre>int main()
{
boost::bind( static_cast&lt; int const&amp; (X::*) () const &gt;( &amp;X::get ), _1 );
}
</pre>
<P>Another, arguably more readable, alternative is to introduce a temporary
variable:</P>
<pre>int main()
{
int const&amp; (X::*get) () const = &amp;X::get;
boost::bind( get, _1 );
}
</pre>
<h3><a name="err_const_arg"><b>const</b> in signatures</a></h3>
<p>Some compilers, including MSVC 6.0 and Borland C++ 5.5.1, have problems with the
top-level <b>const</b> in function signatures:
</p>
<pre>int f(int const);
int main()
{
boost::bind(f, 1); // error
}
</pre>
<p>Workaround: remove the <b>const</b> qualifier from the argument.
</p>
<h3><a name="err_msvc_using">MSVC specific: using boost::bind;</a></h3>
<p>On MSVC (up to version 7.0), when <b>boost::bind</b> is brought into scope with
an using declaration:
</p>
<pre>using boost::bind;
</pre>
<p>the syntax <tt>bind&lt;R&gt;(f, ...)</tt> does not work. Workaround: either use
the qualified name, <b>boost::bind</b>, or use an using directive instead:
</p>
<pre>using namespace boost;
</pre>
<h3><a name="err_msvc_class_template">MSVC specific: class templates shadow function
templates</a></h3>
<p>On MSVC (up to version 7.0), a nested class template named <b>bind</b> will
shadow the function template <b>boost::bind</b>, breaking the <tt>bind&lt;R&gt;(f,
...)</tt> syntax. Unfortunately, some libraries contain nested class
templates named <b>bind</b> (ironically, such code is often an MSVC specific
workaround.)</p>
<P>The workaround is to use the alternative <tt>bind(type&lt;R&gt;(), f, ...)</tt> syntax.</P>
<h3><a name="err_msvc_ellipsis">MSVC specific: ... in signatures treated as type</a></h3>
<p>MSVC (up to version 7.0) treats the ellipsis in a variable argument function
(such as <b>std::printf</b>) as a type. Therefore, it will accept the
(incorrect in the current implementation) form:
</p>
<pre> bind(printf, "%s\n", _1);
</pre>
<p>and will reject the correct version:
</p>
<pre> bind&lt;int&gt;(printf, "%s\n", _1);
</pre>
<h2><a name="Interface">Interface</a></h2>
<h3><a name="Synopsis">Synopsis</a></h3>
<pre>namespace boost
{
// no arguments
template&lt;class R, class F&gt; <i>unspecified-1</i> <A href="#bind_1" >bind</A>(F f);
template&lt;class F&gt; <i>unspecified-1-1</i> <A href="#bind_1_1" >bind</A>(F f);
template&lt;class R&gt; <i>unspecified-2</i> <A href="#bind_2" >bind</A>(R (*f) ());
// one argument
template&lt;class R, class F, class A1&gt; <i>unspecified-3</i> <A href="#bind_3" >bind</A>(F f, A1 a1);
template&lt;class F, class A1&gt; <i>unspecified-3-1</i> <A href="#bind_3_1" >bind</A>(F f, A1 a1);
template&lt;class R, class B1, class A1&gt; <i>unspecified-4</i> <A href="#bind_4" >bind</A>(R (*f) (B1), A1 a1);
template&lt;class R, class T, class A1&gt; <i>unspecified-5</i> <A href="#bind_5" >bind</A>(R (T::*f) (), A1 a1);
template&lt;class R, class T, class A1&gt; <i>unspecified-6</i> <A href="#bind_6" >bind</A>(R (T::*f) () const, A1 a1);
template&lt;class R, class T, class A1&gt; <i>unspecified-6-1</i> <A href="#bind_6_1" >bind</A>(R T::*f, A1 a1);
// two arguments
template&lt;class R, class F, class A1, class A2&gt; <i>unspecified-7</i> <A href="#bind_7" >bind</A>(F f, A1 a1, A2 a2);
template&lt;class F, class A1, class A2&gt; <i>unspecified-7-1</i> <A href="#bind_7_1" >bind</A>(F f, A1 a1, A2 a2);
template&lt;class R, class B1, class B2, class A1, class A2&gt; <i>unspecified-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>unspecified-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>unspecified-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>unspecified-placeholder-type-1</i> _1;
<i>unspecified-placeholder-type-2</i> _2;
<i>unspecified-placeholder-type-3</i> _3;
// implementation defined number of additional placeholder definitions
}
</pre>
<h3><a name="CommonRequirements">Common requirements</a></h3>
<p>All <tt><i>unspecified-N</i></tt> types returned by <b>bind</b> are <b>CopyConstructible</b>.
<tt><i>unspecified-N</i>::result_type</tt> is defined as the return type of <tt><i>unspecified-N</i>::operator()</tt>.</p>
<p>All <tt><i>unspecified-placeholder-N</i></tt> types are <b>CopyConstructible</b>.
Their copy constructors do not throw exceptions.</p>
<h3><a name="CommonDefinitions">Common definitions</a></h3>
<p>The function µ(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>
v<sub>k</sub>, when <tt>x</tt>
is (a copy of) the placeholder _k for some positive integer k;
<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>
<tt>x</tt> otherwise.</li></ul>
<h3><a name="bind">bind</a></h3>
<h4><a name="bind_1">template&lt;class R, class F&gt; <i>unspecified-1</i> bind(F f)</a></h4>
<blockquote>
<p><b>Returns:</b> A function object <i>&#955;</i> such that the expression <tt>&#955;(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>
</blockquote>
<h4><a name="bind_1_1">template&lt;class F&gt; <i>unspecified-1-1</i> bind(F f)</a></h4>
<blockquote>
<p><b>Effects:</b> Equivalent to <tt>bind&lt;typename F::result_type, F&gt;(f);</tt></p>
<p><b>Notes:</b> Implementations are allowed to infer the return type of <b>f</b> via
other means as an extension, without relying on the <tt>result_type</tt> member.</p>
</blockquote>
<h4><a name="bind_2">template&lt;class R&gt; <i>unspecified-2</i> bind(R (*f) ())</a></h4>
<blockquote>
<p><b>Returns:</b> A function object <i>&#955;</i> such that the expression <tt>&#955;(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>
</blockquote>
<h4><a name="bind_3">template&lt;class R, class F, class A1&gt; <i>unspecified-3</i> bind(F
f, A1 a1)</a></h4>
<blockquote>
<p><b>Returns:</b> A function object <i>&#955;</i> such that the expression <tt>&#955;(v<sub>1</sub>,
v<sub>2</sub>, ..., v<sub>m</sub>)</tt> is equivalent to <tt><b>f</b>(µ(<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> or <b>A1</b> throw
an exception.</p>
</blockquote>
<h4><a name="bind_3_1">template&lt;class F, class A1&gt; <i>unspecified-3-1</i> bind(F
f, A1 a1)</a></h4>
<blockquote>
<p><b>Effects:</b> Equivalent to <tt>bind&lt;typename F::result_type, F, A1&gt;(f, a1);</tt></p>
<p><b>Notes:</b> Implementations are allowed to infer the return type of <b>f</b> via
other means as an extension, without relying on the <tt>result_type</tt> member.</p>
</blockquote>
<h4><a name="bind_4">template&lt;class R, class B1, class A1&gt; <i>unspecified-4</i> bind(R
(*f) (B1), A1 a1)</a></h4>
<blockquote>
<p><b>Returns:</b> A function object <i>&#955;</i> such that the expression <tt>&#955;(v<sub>1</sub>,
v<sub>2</sub>, ..., v<sub>m</sub>)</tt> is equivalent to <tt><b>f</b>(µ(<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>
</blockquote>
<h4><a name="bind_5">template&lt;class R, class T, class A1&gt; <i>unspecified-5</i> bind(R
(T::*f) (), A1 a1)</a></h4>
<blockquote>
<p><b>Effects:</b> Equivalent to <tt>bind&lt;R&gt;(<A href="mem_fn.html">boost::mem_fn</A>(f),
a1);</tt></p>
</blockquote>
<h4><a name="bind_6">template&lt;class R, class T, class A1&gt; <i>unspecified-6</i> bind(R
(T::*f) () const, A1 a1)</a></h4>
<blockquote>
<p><b>Effects:</b> Equivalent to <tt>bind&lt;R&gt;(<A href="mem_fn.html">boost::mem_fn</A>(f),
a1);</tt></p>
</blockquote>
<h4><a name="bind_6_1">template&lt;class R, class T, class A1&gt; <i>unspecified-6-1</i>
bind(R T::*f, A1 a1)</a></h4>
<blockquote>
<p><b>Effects:</b> Equivalent to <tt>bind&lt;R&gt;(<A href="mem_fn.html">boost::mem_fn</A>(f),
a1);</tt></p>
</blockquote>
<h4><a name="bind_7">template&lt;class R, class F, class A1, class A2&gt; <i>unspecified-7</i>
bind(F f, A1 a1, A2 a2)</a></h4>
<blockquote>
<p><b>Returns:</b> A function object <i>&#955;</i> such that the expression <tt>&#955;(v<sub>1</sub>,
v<sub>2</sub>, ..., v<sub>m</sub>)</tt> is equivalent to <tt><b>f</b>(µ(<b>a1</b>,
v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>), µ(<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> or <b>A2</b>
throw an exception.</p>
</blockquote>
<h4><a name="bind_7_1">template&lt;class F, class A1, class A2&gt; <i>unspecified-7-1</i>
bind(F f, A1 a1, A2 a2)</a></h4>
<blockquote>
<p><b>Effects:</b> Equivalent to <tt>bind&lt;typename F::result_type, F, A1, A2&gt;(f,
a1, a2);</tt></p>
<p><b>Notes:</b> Implementations are allowed to infer the return type of <b>f</b> via
other means as an extension, without relying on the <tt>result_type</tt> member.</p>
</blockquote>
<h4><a name="bind_8">template&lt;class R, class B1, class B2, class A1, class A2&gt; <i>unspecified-8</i>
bind(R (*f) (B1, B2), A1 a1, A2 a2)</a></h4>
<blockquote>
<p><b>Returns:</b> A function object <i>&#955;</i> such that the expression <tt>&#955;(v<sub>1</sub>,
v<sub>2</sub>, ..., v<sub>m</sub>)</tt> is equivalent to <tt><b>f</b>(µ(<b>a1</b>,
v<sub>1</sub>, v<sub>2</sub>, ..., v<sub>m</sub>), µ(<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> or <b>A2</b> throw
an exception.</p>
</blockquote>
<h4><a name="bind_9">template&lt;class R, class T, class B1, class A1, class A2&gt; <i>unspecified-9</i>
bind(R (T::*f) (B1), A1 a1, A2 a2)</a></h4>
<blockquote>
<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>
</blockquote>
<h4><a name="bind_10">template&lt;class R, class T, class B1, class A1, class A2&gt; <i>unspecified-10</i>
bind(R (T::*f) (B1) const, A1 a1, A2 a2)</a></h4>
<blockquote>
<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>
</blockquote>
<h3><a name="AdditionalOverloads">Additional overloads</a></h3>
<p>Implementations are allowed to provide additional <b>bind</b> overloads in order
to support more arguments or different function pointer variations.</p>
<h2><a name="Implementation">Implementation</a></h2>
<h3><a name="Files">Files</a></h3>
<ul>
<li>
<A href="../../boost/bind.hpp">boost/bind.hpp</A>
(main header)
<li>
<A href="../../boost/bind/bind_cc.hpp">boost/bind/bind_cc.hpp</A>
(used by bind.hpp, do not include directly)
<li>
<A href="../../boost/bind/bind_mf_cc.hpp">boost/bind/bind_mf_cc.hpp</A>
(used by bind.hpp, do not include directly)
<li>
<A href="../../boost/bind/bind_template.hpp">boost/bind/bind_template.hpp</A>
(used by bind.hpp, do not include directly)
<LI>
<A href="../../boost/bind/arg.hpp">boost/bind/arg.hpp</A>
(defines the type of the placeholder arguments)
<LI>
<A href="../../boost/bind/placeholders.hpp">boost/bind/placeholders.hpp</A>
(defines the _1, _2, ... _9 placeholders)
<LI>
<A href="../../boost/bind/apply.hpp">boost/bind/apply.hpp</A> (<STRONG>apply</STRONG>
helper function object)
<LI>
<A href="../../boost/bind/protect.hpp">boost/bind/protect.hpp</A> (<STRONG>protect</STRONG>
helper function)
<LI>
<A href="../../boost/bind/make_adaptable.hpp">boost/bind/make_adaptable.hpp</A>
(<STRONG>make_adaptable</STRONG>
helper function)
<li>
<A href="test/bind_test.cpp">libs/bind/test/bind_test.cpp</A>
(test)
<li>
<A href="bind_as_compose.cpp">libs/bind/bind_as_compose.cpp</A>
(function composition example)
<li>
<A href="bind_visitor.cpp">libs/bind/bind_visitor.cpp</A>
(visitor example)
<li>
<A href="test/bind_stdcall_test.cpp">libs/bind/test/bind_stdcall_test.cpp</A>
(test with __stdcall functions)
<li>
<A href="test/bind_stdcall_mf_test.cpp">libs/bind/test/bind_stdcall_mf_test.cpp</A>
(test with __stdcall member functions)
<li>
<A href="test/bind_fastcall_test.cpp">libs/bind/test/bind_fastcall_test.cpp</A>
(test with __fastcall functions)
<li>
<A href="test/bind_fastcall_mf_test.cpp">libs/bind/test/bind_fastcall_mf_test.cpp</A>
(test with __fastcall member functions)</li></ul>
<h3><a name="Dependencies">Dependencies</a></h3>
<ul>
<li>
<A href="../config/config.htm">Boost.Config</A>
<li>
<A href="ref.html">boost/ref.hpp</A>
<li>
<A href="mem_fn.html">boost/mem_fn.hpp</A>
<li>
<A href="../../boost/type.hpp">boost/type.hpp</A></li>
</ul>
<h3><a name="NumberOfArguments">Number of Arguments</a></h3>
<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><a name="stdcall">"__stdcall", "__cdecl", "__fastcall", and "pascal" Support</a></h3>
<p>Some platforms allow several types of (member) functions that differ by their <b>calling
convention</b> (the rules by which the function is invoked: how are
arguments passed, how is the return value handled, and who cleans up the stack
- if any.)</p>
<p>For example, Windows API functions and COM interface member functions use a
calling convention known as <b>__stdcall</b>.Borland VCL components use <STRONG>__fastcall</STRONG>.
Mac toolbox functions use a <b>pascal</b> calling convention.</p>
<p>To use <b>bind</b> with <b>__stdcall</b> functions, <b>#define</b> the macro <b>BOOST_BIND_ENABLE_STDCALL</b>
before including <b>&lt;boost/bind.hpp&gt;</b>.</p>
<p>To use <b>bind</b> with <b>__stdcall</b> <b>member</b> functions, <b>#define</b>
the macro <b>BOOST_MEM_FN_ENABLE_STDCALL</b> before including <b>&lt;boost/bind.hpp&gt;</b>.</p>
<P>To use <B>bind</B> with <B>__fastcall</B> functions, <B>#define</B> the macro <B>BOOST_BIND_ENABLE_FASTCALL</B>
before including <B>&lt;boost/bind.hpp&gt;</B>.</P>
<P>To use <B>bind</B> with <B>__fastcall</B> <B>member</B> functions, <B>#define</B>
the macro <B>BOOST_MEM_FN_ENABLE_FASTCALL</B> before including <B>&lt;boost/bind.hpp&gt;</B>.</P>
<P>To use <b>bind</b> with <b>pascal</b> functions, <b>#define</b> the macro <b>BOOST_BIND_ENABLE_PASCAL</b>
before including <b>&lt;boost/bind.hpp&gt;</b>.</P>
<P>To use <B>bind</B> with <B>__cdecl</B> <B>member</B> functions, <B>#define</B> the
macro <B>BOOST_MEM_FN_ENABLE_CDECL</B> before including <B>&lt;boost/bind.hpp&gt;</B>.</P>
<P><STRONG>It is best to define these macros in the project options, via -D on the
command line, or as the first line in the translation unit (.cpp file) where
bind is used.</STRONG> Not following this rule can lead to obscure errors
when a header includes bind.hpp before the macro has been defined.</P>
<p>[Note: this is a non-portable extension. It is not part of the interface.]</p>
<p>[Note: Some compilers provide only minimal support for the <b>__stdcall</b> keyword.]</p>
<h3><a name="visit_each"><b>visit_each</b> support</a></h3>
<p>Function objects returned by <b>bind</b> support the experimental and
undocumented, as of yet, <b>visit_each</b> enumeration interface.</p>
<p>See <A href="bind_visitor.cpp">bind_visitor.cpp</A> for an example.</p>
<h2><a name="Acknowledgements">Acknowledgements</a></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ärvi;
<li>
The <a href="../lambda/index.html">Lambda Library</a>
(now part of Boost) by Jaakko Järvi and Gary Powell (the successor to the
Binder Library);
<li>
<a href="http://more.sourceforge.net/">Extensions to the STL</a> by Petter
Urkedal.</li></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.html">
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ärvi.
</p>
<p>Dave Abrahams fixed a MSVC-specific conflict between <b>bind</b> and the <A href="../utility/iterator_adaptors.htm">
iterator adaptors library</A>.
</p>
<p>Dave Abrahams modified <b>bind</b> and <b>mem_fn</b> to support void returns on
deficient compilers.
</p>
<p>Mac Murrett contributed the "pascal" support enabled by
BOOST_BIND_ENABLE_PASCAL.
</p>
<p>The alternative <tt>bind(type&lt;R&gt;(), f, ...)</tt> syntax was inspired by a
discussion with Dave Abrahams and Joel de Guzman.</p>
<p><br>
<br>
<br>
<small>Copyright © 2001, 2002 by Peter Dimov and Multi Media Ltd. Copyright
2003-2008 Peter Dimov. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
<head>
<title>Boost.Bind</title>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=doc/html/bind.html">
<style>
body {
background: #fff;
color: #000;
}
a {
color: #00f;
text-decoration: none;
}
</style>
</head>
<body>
<p>
Automatic redirection failed, please go to
<a href="doc/html/bind.html">doc/html/bind.html</a>
</p>
<p>
&copy; 2001, 2002 Peter Dimov and Multi Media Ltd.<br>
&copy; 2003-2008 Peter Dimov
</p>
</body>
</html>

1
doc/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/html/

View File

@@ -1,13 +1,50 @@
# Copyright (c) 2002 Douglas Gregor <doug.gregor -at- gmail.com>
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
project boost/doc ;
import boostbook : boostbook ;
boostbook ref-doc : ref.xml
:
<format>pdf:<xsl:param>boost.url.prefix=http://www.boost.org/doc/libs/release/doc/html
;
project doc/bind ;
import boostbook ;
import quickbook ;
xml bind_ : bind.qbk ;
boostbook standalone_bind
:
bind_
:
<xsl:param>boost.root=../../../..
# File name of HTML output:
<xsl:param>root.filename=bind
# How far down we chunk nested sections, basically all of them:
<xsl:param>chunk.section.depth=0
# Don't put the first section on the same page as the TOC:
<xsl:param>chunk.first.sections=0
# How far down sections get TOC's
<xsl:param>toc.section.depth=2
# Max depth in each TOC:
<xsl:param>toc.max.depth=2
# How far down we go with TOC's
<xsl:param>generate.section.toc.level=0
;
xml mem_fn_ : mem_fn.qbk ;
boostbook standalone_mem_fn
:
mem_fn_
:
<xsl:param>boost.root=../../../..
# File name of HTML output:
<xsl:param>root.filename=mem_fn
# How far down we chunk nested sections, basically all of them:
<xsl:param>chunk.section.depth=0
# Don't put the first section on the same page as the TOC:
<xsl:param>chunk.first.sections=0
# How far down sections get TOC's
<xsl:param>toc.section.depth=2
# Max depth in each TOC:
<xsl:param>toc.max.depth=2
# How far down we go with TOC's
<xsl:param>generate.section.toc.level=0
;

35
doc/bind.qbk Normal file
View File

@@ -0,0 +1,35 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2008 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[library Boost.Bind
[quickbook 1.6]
[id bind]
[copyright 2001, 2002 Peter Dimov and Multi Media Ltd.]
[copyright 2003-2008 Peter Dimov]
[dirname bind]
[license Distributed under the
[@http://boost.org/LICENSE_1_0.txt Boost Software License,
Version 1.0].
]
]
[template simplesect[title]
[block '''<simplesect><title>'''[title]'''</title>''']]
[template endsimplesect[]
[block '''</simplesect>''']]
[include bind/purpose.qbk]
[include bind/examples.qbk]
[include bind/limitations.qbk]
[include bind/faq.qbk]
[include bind/troubleshooting.qbk]
[include bind/interface.qbk]
[include bind/implementation.qbk]
[include bind/acknowledgements.qbk]

View File

@@ -0,0 +1,48 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2008 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[section:acknowledgements Acknowledgements]
Earlier efforts that have influenced the library design:
* The [@http://staff.cs.utu.fi/BL/ Binder Library] by Jaakko J\u00E4rvi;
* The [@boost:/libs/lambda/index.html Lambda Library] (now part of Boost) by
Jaakko J\u00E4rvi and Gary Powell (the successor to the Binder Library);
* [@http://more.sourceforge.net/ Extensions to the STL] by Petter Urkedal.
Doug Gregor suggested that a visitor mechanism would allow `bind` to
interoperate with a signal/slot library.
John Maddock fixed a MSVC-specific conflict between `bind` and the
[@boost:/libs/type_traits/index.html type traits library].
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.
The precise semantics of `bind` were refined in discussions with Jaakko
J\u00E4rvi.
Dave Abrahams fixed a MSVC-specific conflict between `bind` and the
[@boost:/libs/utility/iterator_adaptors.htm iterator adaptors library].
Dave Abrahams modified `bind` and `mem_fn` to support `void` returns on
deficient compilers.
Mac Murrett contributed the "pascal" support enabled by
`BOOST_BIND_ENABLE_PASCAL`.
The alternative `bind(type<R>(), f, ...)` syntax was inspired by a discussion
with Dave Abrahams and Joel de Guzman.
This documentation was ported to Quickbook by Agustín Bergé.
[endsect]

70
doc/bind/examples.qbk Normal file
View File

@@ -0,0 +1,70 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2008 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[section:examples Examples]
[section Using bind with standard algorithms]
class image;
class animation
{
public:
void advance(int ms);
bool inactive() const;
void render(image & target) const;
};
std::vector<animation> anims;
template<class C, class P> void erase_if(C & 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(&animation::advance, _1, ms));
erase_if(anims, boost::mem_fn(&animation::inactive));
}
void render(image & target)
{
std::for_each(anims.begin(), anims.end(), boost::bind(&animation::render, _1, boost::ref(target)));
}
[endsect]
[section Using bind with Boost.Function]
class button
{
public:
``[@boost:/libs/function/index.html `boost::function`]``<void()> onClick;
};
class player
{
public:
void play();
void stop();
};
button playButton, stopButton;
player thePlayer;
void connect()
{
playButton.onClick = boost::bind(&player::play, &thePlayer);
stopButton.onClick = boost::bind(&player::stop, &thePlayer);
}
[endsect]
[endsect]

99
doc/bind/faq.qbk Normal file
View File

@@ -0,0 +1,99 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2008 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[section:faq Frequently Asked Questions]
[section Why doesn't this compile?]
See the dedicated [link bind.troubleshooting Troubleshooting section].
[endsect]
[section Why does this compile? It should not.]
Probably because you used the general `bind<R>(f, ...)` syntax, thereby
instructing `bind` to not "inspect" f to detect arity and return type errors.
[endsect]
[section:Q_forms What is the difference between `bind(f, ...)` and `bind<R>(f, ...)`?]
The first form instructs `bind` to inspect the type of `f` in order to
determine its arity (number of arguments) and return type. Arity errors will
be detected at "bind time". This syntax, of course, places some requirements
on `f`. It must be a function, function pointer, member function pointer, or a
function object that defines a nested type named `result_type`; in short, it
must be something that `bind` can recognize.
The second form instructs `bind` to not attempt to recognize the type of `f`.
It is generally used with function objects that do not, or cannot, expose
`result_type`, but it can also be used with nonstandard functions. For example,
the current implementation does not automatically recognize variable-argument
functions like `printf`, so you will have to use `bind<int>(printf, ...)`.
Note that an alternative `bind(type<R>(), f, ...)` syntax is supported for
portability reasons.
Another important factor to consider is that compilers without partial
template specialization or function template partial ordering support cannot
handle the first form when `f` is a function object, and in most cases will
not handle the second form when `f` is a function (pointer) or a member
function pointer.
[endsect]
[section Does bind work with Windows API functions?]
Yes, if you [link bind.implementation.stdcall `#define
BOOST_BIND_ENABLE_STDCALL`]. An alternative is to treat the function as a
[link bind.purpose.with_function_objects generic function object] and use the
`bind<R>(f, ...)` syntax.
[endsect]
[section Does bind work with COM methods?]
Yes, if you [link bind.implementation.stdcall `#define
BOOST_MEM_FN_ENABLE_STDCALL`].
[endsect]
[section Does bind work with Mac toolbox functions?]
Yes, if you [link bind.implementation.stdcall `#define
BOOST_BIND_ENABLE_PASCAL`]. An alternative is to treat the function as a [link
bind.purpose.with_function_objects generic function object] and use the
`bind<R>(f, ...)` syntax.
[endsect]
[section Does bind work with extern "C" functions?]
Sometimes. On some platforms, pointers to extern "C" functions are equivalent
to "ordinary" function pointers, so they work fine. Other platforms treat them
as different types. A platform-specific implementation of `bind` is expected
to handle the problem transparently; this implementation does not. As usual,
the workaround is to treat the function as a [link
bind.purpose.with_function_objects generic function object] and use the
`bind<R>(f, ...)` syntax.
[endsect]
[section Why doesn't bind automatically recognize nonstandard functions?]
Non-portable extensions, in general, should default to off to prevent vendor
lock-in. Had the [link bind.implementation.stdcall appropriate macros] been
defined automatically, you could have accidentally taken advantage of them
without realizing that your code is, perhaps, no longer portable. In addition,
some compilers have the option to make `__stdcall` (`__fastcall`) their
default calling convention, in which case no separate support would be
necessary.
[endsect]
[endsect]

View File

@@ -0,0 +1,98 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2008 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[section:implementation Implementation]
[section Files]
* [@../../include/boost/bind.hpp boost/bind.hpp] (main header)
* [@../../include/boost/bind/bind_cc.hpp boost/bind/bind_cc.hpp] (used by `bind.hpp`, do not include directly)
* [@../../include/boost/bind/bind_mf_cc.hpp boost/bind/bind_mf_cc.hpp] (used by `bind.hpp`, do not include directly)
* [@../../include/boost/bind/bind_template.hpp boost/bind/bind_template.hpp] (used by `bind.hpp`, do not include directly)
* [@../../include/boost/bind/arg.hpp boost/bind/arg.hpp] (defines the type of the placeholder arguments)
* [@../../include/boost/bind/placeholders.hpp boost/bind/placeholders.hpp] (defines the `_1`, `_2`, ... `_9` placeholders)
* [@../../include/boost/bind/apply.hpp boost/bind/apply.hpp] (`apply` helper function object)
* [@../../include/boost/bind/protect.hpp boost/bind/protect.hpp] (`protect` helper function)
* [@../../include/boost/bind/make_adaptable.hpp boost/bind/make_adaptable.hpp] (`make_adaptable` helper function)
* [@../../test/bind_test.cpp libs/bind/test/bind_test.cpp] (test)
* [@../../bind_as_compose.cpp libs/bind/bind_as_compose.cpp] (function composition example)
* [@../../bind_visitor.cpp libs/bind/bind_visitor.cpp] (visitor example)
* [@../../test/bind_stdcall_test.cpp libs/bind/test/bind_stdcall_test.cpp] (test with `__stdcall` functions)
* [@../../test/bind_stdcall_mf_test.cpp libs/bind/test/bind_stdcall_mf_test.cpp] (test with `__stdcall` member functions)
* [@../../test/bind_fastcall_test.cpp libs/bind/test/bind_fastcall_test.] (test with `__fastcall` functions)
* [@../../test/bind_fastcall_mf_test.cpp libs/bind/test/bind_fastcall_mf_test.cpp] (test with `__fastcall` member functions)
[endsect]
[section Dependencies]
* [@boost:/libs/config/config.htm Boost.Config]
* [@boost:/libs/core/doc/html/core/ref.html boost/ref.hpp]
* [@boost:/libs/bind/mem_fn.html boost/mem_fn.hpp]
* [@boost:/boost/type.hpp boost/type.hpp]
[endsect]
[section Number of Arguments]
This implementation supports function objects with up to nine arguments. This
is an implementation detail, not an inherent limitation of the design.
[endsect]
[section:stdcall `__stdcall`, `__cdecl`, `__fastcall`, and `pascal` Support]
Some platforms allow several types of (member) functions that differ by their
calling convention (the rules by which the function is invoked: how are
arguments passed, how is the return value handled, and who cleans up the stack
- if any.)
For example, Windows API functions and COM interface member functions use a
calling convention known as `__stdcall`. Borland VCL components use
`__fastcall`. Mac toolbox functions use a `pascal` calling convention.
To use `bind` with `__stdcall` functions, `#define` the macro
`BOOST_BIND_ENABLE_STDCALL` before including `<boost/bind.hpp>`.
To use `bind` with `__stdcall` member functions, `#define` the macro
`BOOST_MEM_FN_ENABLE_STDCALL` before including `<boost/bind.hpp>`.
To use `bind` with `__fastcall` functions, `#define` the macro
`BOOST_BIND_ENABLE_FASTCALL` before including `<boost/bind.hpp>`.
To use `bind` with `__fastcall` member functions, `#define` the macro
`BOOST_MEM_FN_ENABLE_FASTCALL` before including `<boost/bind.hpp>`.
To use `bind` with `pascal` functions, `#define` the macro
`BOOST_BIND_ENABLE_PASCAL` before including `<boost/bind.hpp>`.
To use `bind` with `__cdecl` member functions, `#define` the macro
`BOOST_MEM_FN_ENABLE_CDECL` before including `<boost/bind.hpp>`.
[*It is best to define these macros in the project options, via `-D` on the
command line, or as the first line in the translation unit (.cpp file) where
`bind` is used.] Not following this rule can lead to obscure errors when a
header includes `bind.hpp` before the macro has been defined.
/[Note:/ this is a non-portable extension. It is not part of the interface./]/
/[Note:/ Some compilers provide only minimal support for the `__stdcall` keyword./]/
[endsect]
[section `visit_each` support]
Function objects returned by `bind` support the experimental and undocumented,
as of yet, `visit_each` enumeration interface.
See [@../../bind_visitor.cpp bind_visitor.cpp] for an example.
[endsect]
[endsect]

216
doc/bind/interface.qbk Normal file
View File

@@ -0,0 +1,216 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2008 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[section:interface Interface]
[section:synopsys Synopsis]
namespace boost
{
// no arguments
template<class R, class F> ``/unspecified-1/`` ``[link bind_1 `bind`]``(F f);
template<class F> ``/unspecified-1-1/`` ``[link bind_1_1 `bind`]``(F f);
template<class R> ``/unspecified-2/`` ``[link bind_2 `bind`]``(R (*f) ());
// one argument
template<class R, class F, class A1> ``/unspecified-3/`` ``[link bind_3 `bind`]``(F f, A1 a1);
template<class F, class A1> ``/unspecified-3-1/`` ``[link bind_3_1 `bind`]``(F f, A1 a1);
template<class R, class B1, class A1> ``/unspecified-4/`` ``[link bind_4 `bind`]``(R (*f) (B1), A1 a1);
template<class R, class T, class A1> ``/unspecified-5/`` ``[link bind_5 `bind`]``(R (T::*f) (), A1 a1);
template<class R, class T, class A1> ``/unspecified-6/`` ``[link bind_6 `bind`]``(R (T::*f) () const, A1 a1);
template<class R, class T, class A1> ``/unspecified-6-1/`` ``[link bind_6_1 `bind`]``(R T::*f, A1 a1);
// two arguments
template<class R, class F, class A1, class A2> ``/unspecified-7/`` ``[link bind_7 `bind`]``(F f, A1 a1, A2 a2);
template<class F, class A1, class A2> ``/unspecified-7-1/`` ``[link bind_7_1 `bind`]``(F f, A1 a1, A2 a2);
template<class R, class B1, class B2, class A1, class A2> ``/unspecified-8/`` ``[link bind_8 `bind`]``(R (*f) (B1, B2), A1 a1, A2 a2);
template<class R, class T, class B1, class A1, class A2> ``/unspecified-9/`` ``[link bind_9 `bind`]``(R (T::*f) (B1), A1 a1, A2 a2);
template<class R, class T, class B1, class A1, class A2> ``/unspecified-10/`` ``[link bind_10 `bind`]``(R (T::*f) (B1) const, A1 a1, A2 a2);
// implementation defined number of additional overloads for more arguments
}
namespace
{
``/unspecified-placeholder-type-1/`` _1;
``/unspecified-placeholder-type-2/`` _2;
``/unspecified-placeholder-type-3/`` _3;
// implementation defined number of additional placeholder definitions
}
[endsect]
[section Common requirements]
All /unspecified-N/ types returned by `bind` are /CopyConstructible/. /unspecified-N/`::result_type` is defined as the return type of /unspecified-N/`::operator()`.
All /unspecified-placeholder-N/ types are /CopyConstructible/. Their copy constructors do not throw exceptions.
[endsect]
[section Common definitions]
The function \u03BC`(x, v1, v2, ..., vm)`, where `m` is a nonnegative integer, is
defined as:
* `x.get()`, when `x` is of type [@boost:/libs/core/doc/html/core/ref.html `boost::reference_wrapper`]`<T>` for some type
`T`;
* `vk`, when `x` is (a copy of) the placeholder /_k/ for some positive integer
/k/;
* `x(v1, v2, ..., vm)` when `x` is (a copy of) a function object returned by
`bind`;
* `x` otherwise.
[endsect]
[section `bind`]
[#bind_1]
template<class R, class F> ``/unspecified-1/`` bind(F f)
* /Returns:/ A function object \u03BB such that the expression \u03BB`(v1, v2, ..., vm)`
is equivalent to `f()`, implicitly converted to `R`.
* /Throws:/ Nothing unless the copy constructor of `F` throws an exception.
[#bind_1_1]
template<class F> ``/unspecified-1-1/`` bind(F f)
* /Effects:/ Equivalent to `bind<typename F::result_type, F>(f)`.
* /Notes:/ Implementations are allowed to infer the return type of `f` via other
means as an extension, without relying on the `result_type` member.
[#bind_2]
template<class R> ``/unspecified-2/`` bind(R (*f) ())
* /Returns:/ A function object \u03BB such that the expression \u03BB`(v1, v2, ..., vm)`
is equivalent to `f()`.
* /Throws:/ Nothing.
[#bind_3]
template<class R, class F, class A1> ``/unspecified-3/`` bind(F f, A1 a1)
* /Returns:/ A function object \u03BB such that the expression \u03BB`(v1, v2, ..., vm)`
is equivalent to `f(`\u03BC`(a1, v1, v2, ..., vm))`, implicitly converted to `R`.
* /Throws:/ Nothing unless the copy constructors of `F` or `A1` throw an exception.
[#bind_3_1]
template<class F, class A1> ``/unspecified-3-1/`` bind(F f, A1 a1)
* /Effects:/ Equivalent to `bind<typename F::result_type, F, A1>(f, a1)`.
* /Notes:/ Implementations are allowed to infer the return type of `f` via other
means as an extension, without relying on the `result_type` member.
[#bind_4]
template<class R, class B1, class A1> ``/unspecified-4/`` bind(R (*f) (B1), A1 a1)
* /Returns:/ A function object \u03BB such that the expression \u03BB`(v1, v2, ..., vm)`
is equivalent to `f(`\u03BC`(a1, v1, v2, ..., vm))`.
* /Throws:/ Nothing unless the copy constructor of `A1` throws an exception.
[#bind_5]
template<class R, class T, class A1> ``/unspecified-5/`` bind(R (T::*f) (), A1 a1)
* /Effects:/ Equivalent to `bind<R>(`[@boost:/libs/bind/mem_fn.html `boost::mem_fn`]`(f), a1)`.
[#bind_6]
template<class R, class T, class A1> ``/unspecified-6/`` bind(R (T::*f) () const, A1 a1)
* /Effects:/ Equivalent to `bind<R>(`[@boost:/libs/bind/mem_fn.html `boost::mem_fn`]`(f), a1)`.
[#bind_6_1]
template<class R, class T, class A1> ``/unspecified-6-1/`` bind(R T::*f, A1 a1)
* /Effects:/ Equivalent to `bind<R>(`[@boost:/libs/bind/mem_fn.html `boost::mem_fn`]`(f), a1)`.
[#bind_7]
template<class R, class F, class A1, class A2> ``/unspecified-7/`` bind(F f, A1 a1, A2 a2)
* /Returns:/ A function object \u03BB such that the expression \u03BB`(v1, v2, ..., vm)`
is equivalent to `f(`\u03BC`(a1, v1, v2, ..., vm), `\u03BC`(a2, v1, v2, ..., vm))`,
implicitly converted to `R`.
* /Throws:/ Nothing unless the copy constructors of `F`, `A1` or `A2` throw an
exception.
[#bind_7_1]
template<class F, class A1, class A2> ``/unspecified-7-1/`` bind(F f, A1 a1, A2 a2)
* /Effects:/ Equivalent to `bind<typename F::result_type, F, A1, A2>(f, a1, a2)`.
* /Notes:/ Implementations are allowed to infer the return type of `f` via other
means as an extension, without relying on the `result_type` member.
[#bind_8]
template<class R, class B1, class B2, class A1, class A2> ``/unspecified-8/`` bind(R (*f) (B1, B2), A1 a1, A2 a2)
* /Returns:/ A function object \u03BB such that the expression \u03BB`(v1, v2, ..., vm)`
is equivalent to `f(`\u03BC`(a1, v1, v2, ..., vm), `\u03BC`(a2, v1, v2, ..., vm))`.
* /Throws:/ Nothing unless the copy constructors of `A1` or `A2` throw an exception.
[#bind_9]
template<class R, class T, class B1, class A1, class A2> ``/unspecified-9/`` bind(R (T::*f) (B1), A1 a1, A2 a2)
* /Effects:/ Equivalent to `bind<R>(`[@boost:/libs/bind/mem_fn.html `boost::mem_fn`]`(f), a1, a2)`.
[#bind_10]
template<class R, class T, class B1, class A1, class A2> ``/unspecified-10/`` bind(R (T::*f) (B1) const, A1 a1, A2 a2)
* /Effects:/ Equivalent to `bind<R>(`[@boost:/libs/bind/mem_fn.html `boost::mem_fn`]`(f), a1, a2)`.
[endsect]
[section Additional overloads]
Implementations are allowed to provide additional `bind` overloads in order to
support more arguments or different function pointer variations.
[endsect]
[endsect]

37
doc/bind/limitations.qbk Normal file
View File

@@ -0,0 +1,37 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2008 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[section:limitations Limitations]
As a general rule, the function objects generated by `bind` take their
arguments by reference and cannot, therefore, accept non-const temporaries or
literal constants. This is an inherent limitation of the C++ language in its
current (2003) incarnation, known as the [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1385.htm forwarding problem].
(It will be fixed in the next standard, usually called C++0x.)
The library uses signatures of the form
template<class T> void f(T & t);
to accept arguments of arbitrary types and pass them on unmodified. As noted,
this does not work with non-const r-values.
On compilers that support partial ordering of function templates, a possible
solution is to add an overload:
template<class T> void f(T & t);
template<class T> void f(T const & t);
Unfortunately, this requires providing 512 overloads for nine arguments, which
is impractical. The library chooses a small subset: for up to two arguments,
it provides the const overloads in full, for arities of three and more it
provides a single additional overload with all of the arguments taken by const
reference. This covers a reasonable portion of the use cases.
[endsect]

273
doc/bind/purpose.qbk Normal file
View File

@@ -0,0 +1,273 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2008 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[section:purpose Purpose]
`boost::bind` is a generalization of the standard functions `std::bind1st` and
`std::bind2nd`. 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. `bind` does
not place any requirements on the function object; in particular, it does not
need the `result_type`, `first_argument_type` and `second_argument_type`
standard typedefs.
[section Using bind with functions and function pointers]
Given these definitions:
int f(int a, int b)
{
return a + b;
}
int g(int a, int b, int c)
{
return a + b + c;
}
`bind(f, 1, 2)` will produce a "nullary" function object that takes no
arguments and returns `f(1, 2)`. Similarly, `bind(g, 1, 2, 3)()` is equivalent
`to g(1, 2, 3)`.
It is possible to selectively bind only some of the arguments.
`bind(f, _1, 5)(x)` is equivalent to `f(x, 5)`; here `_1` is a /placeholder/
argument that means "substitute with the first input argument."
For comparison, here is the same operation expressed with the standard library
primitives:
std::bind2nd(std::ptr_fun(f), 5)(x);
`bind` covers the functionality of `std::bind1st` as well:
std::bind1st(std::ptr_fun(f), 5)(x); // f(5, x)
bind(f, 5, _1)(x); // f(5, x)
`bind` can handle functions with more than two arguments, and its argument
substitution mechanism is more general:
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)
Note that, in the last example, the function object produced by
`bind(g, _1, _1, _1)` does not contain references to any arguments beyond the
first, but it can still be used with more than one argument. Any extra
arguments are silently ignored, just like the first and the second argument
are ignored in the third example.
The arguments that `bind` takes are copied and held internally by the returned
function object. For example, in the following code:
int i = 5;
bind(f, i, _1);
a copy of the value of `i` is stored into the function object.
[@boost:/libs/core/doc/html/core/ref.html `boost::ref`] and
[@boost:/libs/core/doc/html/core/ref.html `boost::cref`] can be used to make the function
object store a reference to an object, rather than a copy:
int i = 5;
bind(f, ref(i), _1);
bind(f, cref(i), _1);
[endsect]
[section:with_function_objects Using bind with function objects]
`bind` is not limited to functions; it accepts arbitrary function objects. In
the general case, the return type of the generated function object's
`operator()` has to be specified explicitly (without a `typeof` operator the
return type cannot be inferred):
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<int>(f, _1, _1)(x); // f(x, x), i.e. zero
Some compilers have trouble with the `bind<R>(f, ...)` syntax. For portability
reasons, an alternative way to express the above is supported:
boost::bind(boost::type<int>(), f, _1, _1)(x);
Note, however, that the alternative syntax is provided only as a workaround.
It is not part of the interface.
When the function object exposes a nested type named `result_type`, the explicit
return type can be omitted:
int x = 8;
bind(std::less<int>(), _1, 9)(x); // x < 9
/[Note:/ the ability to omit the return type is not available on all compilers./]/
By default, `bind` makes a copy of the provided function object. `boost::ref`
and `boost::cref` can be used to make it store a reference to the function
object, rather than a copy. This can be useful when the function object is
non-copyable, expensive to copy, or contains state; of course, in this case
the programmer is expected to ensure that the function object is not destroyed
while it's still being used.
struct F2
{
int s;
typedef void result_type;
void operator()(int x) { s += x; }
};
F2 f2 = { 0 };
int a[] = { 1, 2, 3 };
std::for_each(a, a+3, bind(ref(f2), _1));
assert(f2.s == 6);
[endsect]
[section Using bind with pointers to members]
Pointers to member functions and pointers to data members are not function
objects, because they do not support `operator()`. For convenience, `bind`
accepts member pointers as its first argument, and the behavior is as if
[@boost:/libs/bind/mem_fn.html `boost::mem_fn`] has been used to convert the
member pointer into a function object. In other words, the expression
bind(&X::f, args)
is equivalent to
bind<R>(``[@boost:/libs/bind/mem_fn.html `mem_fn`]``(&X::f), args)
where `R` is the return type of `X::f` (for member functions) or the type of
the member (for data members.)
/[Note:/ `mem_fn` 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 `mem_fn`
[@boost:/libs/bind/mem_fn.html documentation]./]/
Example:
struct X
{
bool f(int a);
};
X x;
shared_ptr<X> p(new X);
int i = 5;
bind(&X::f, ref(x), _1)(i); // x.f(i)
bind(&X::f, &x, _1)(i); // (&x)->f(i)
bind(&X::f, x, _1)(i); // (internal copy of x).f(i)
bind(&X::f, p, _1)(i); // (internal copy of p)->f(i)
The last two examples are interesting in that they produce "self-contained"
function objects. `bind(&X::f, x, _1)` stores a copy of `x`.
`bind(&X::f, p, _1)` stores a copy of `p`, and since `p` is a
[@boost:/libs/smart_ptr/shared_ptr.htm `boost::shared_ptr`], the function
object retains a reference to its instance of `X` and will remain valid even
when `p` goes out of scope or is `reset()`.
[endsect]
[section Using nested binds for function composition]
Some of the arguments passed to `bind` may be nested /bind expressions/
themselves:
bind(f, bind(g, _1))(x); // f(g(x))
The inner /bind expressions/ are evaluated, in unspecified order, before the
outer `bind` when the function object is called; the results of the evaluation
are then substituted in their place when the outer `bind` is evaluated. In the
example above, when the function object is called with the argument list `(x)`,
`bind(g, _1)(x)` is evaluated first, yielding `g(x)`, and then
`bind(f, g(x))(x)` is evaluated, yielding the final result `f(g(x))`.
This feature of `bind` can be used to perform function composition. See
[@../../bind_as_compose.cpp bind_as_compose.cpp] for an example that
demonstrates how to use `bind` to achieve similar functionality to
[@http://www.boost.org/doc/libs/1_31_0/libs/compose/index.htm Boost.Compose].
Note that the first argument - the bound function object - is not evaluated,
even when it's a function object that is produced by `bind` or a /placeholder/
argument, so the example below does not work as expected:
typedef void (*pf)(int);
std::vector<pf> v;
std::for_each(v.begin(), v.end(), bind(_1, 5));
The desired effect can be achieved via a helper function object `apply` that
applies its first argument, as a function object, to the rest of its argument
list. For convenience, an implementation of `apply` is provided in the
[@../../include/boost/bind/apply.hpp apply.hpp] header file. Here is how the
modified version of the previous example looks like:
typedef void (*pf)(int);
std::vector<pf> v;
std::for_each(v.begin(), v.end(), bind(apply<void>(), _1, 5));
Although the first argument is, by default, not evaluated, all other arguments
are. Sometimes it is necessary not to evaluate arguments subsequent to the
first, even when they are nested /bind subexpressions/. This can be achieved
with the help of another function object, `protect`, that masks the type so
that `bind` does not recognize and evaluate it. When called, protect simply
forwards the argument list to the other function object unmodified.
The header [@../../include/boost/bind/protect.hpp protect.hpp] contains an
implementation of `protect`. To `protect` a bind function object from
evaluation, use `protect(bind(f, ...))`.
[endsect]
[section Overloaded operators (new in Boost 1.33)]
For convenience, the function objects produced by `bind` overload the logical
not operator `!` and the relational and logical operators `==, !=, <, <=, >,
>=, &&, ||`.
`!bind(f, ...)` is equivalent to `bind(logical_not(), bind(f, ...))`, where
`logical_not` is a function object that takes one argument `x` and returns
`!x`.
`bind(f, ...) op x`, where _op_ is a relational or logical operator, is
equivalent to `bind(relation(), bind(f, ...), x)`, where `relation` is a
function object that takes two arguments `a` and `b` and returns `a op b`.
What this means in practice is that you can conveniently negate the result of
`bind`:
std::remove_if(first, last, !bind(&X::visible, _1)); // remove invisible objects
and compare the result of `bind` against a value:
std::find_if(first, last, bind(&X::name, _1) == "Peter");
std::find_if(first, last, bind(&X::name, _1) == "Peter" || bind(&X::name, _1) == "Paul");
against a /placeholder/:
bind(&X::name, _1) == _2
or against another /bind expression/:
std::sort(first, last, bind(&X::name, _1) < bind(&X::name, _2)); // sort by name
[endsect]
[endsect]

View File

@@ -0,0 +1,268 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2008 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[section:troubleshooting Troubleshooting]
[section Incorrect number of arguments]
In a `bind(f, a1, a2, ..., aN)` expression, the function object `f` must be
able to take exactly N arguments. This error is normally detected at "bind
time"; in other words, the compilation error is reported on the line where
`bind()` is invoked:
int f(int, int);
int main()
{
boost::bind(f, 1); // error, f takes two arguments
boost::bind(f, 1, 2); // OK
}
A common variation of this error is to forget that member functions have an
implicit "this" argument:
struct X
{
int f(int);
}
int main()
{
boost::bind(&X::f, 1); // error, X::f takes two arguments
boost::bind(&X::f, _1, 1); // OK
}
[endsect]
[section The function object cannot be called with the specified arguments]
As in normal function calls, the function object that is bound must be
compatible with the argument list. The incompatibility will usually be
detected by the compiler at "call time" and the result is typically an error
in `bind.hpp` on a line that looks like:
return f(a[a1_], a[a2_]);
An example of this kind of error:
int f(int);
int main()
{
boost::bind(f, "incompatible"); // OK so far, no call
boost::bind(f, "incompatible")(); // error, "incompatible" is not an int
boost::bind(f, _1); // OK
boost::bind(f, _1)("incompatible"); // error, "incompatible" is not an int
}
[endsect]
[section Accessing an argument that does not exist]
The placeholder `_N` selects the argument at position `N` from the argument
list passed at "call time." Naturally, it is an error to attempt to access
beyond the end of this list:
int f(int);
int main()
{
boost::bind(f, _1); // OK
boost::bind(f, _1)(); // error, there is no argument number 1
}
The error is usually reported in `bind.hpp`, at a line similar to:
return f(a[a1_]);
When emulating `std::bind1st(f, a)`, a common mistake of this category is to
type `bind(f, a, _2)` instead of the correct `bind(f, a, _1)`.
[endsect]
[section Inappropriate use of `bind(f, ...)`]
The `bind(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form] causes automatic
recognition of the type of `f`. It will not work with arbitrary function
objects; `f` must be a function or a member function pointer.
It is possible to use this form with function objects that define
`result_type`, but only on compilers that support partial specialization and
partial ordering. In particular, MSVC up to version 7.0 does not support this
syntax for function objects.
[endsect]
[section Inappropriate use of `bind<R>(f, ...)`]
The `bind<R>(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form] supports
arbitrary function objects.
It is possible (but not recommended) to use this form with functions or member
function pointers, but only on compilers that support partial ordering. In
particular, MSVC up to version 7.0 does not fully support this syntax for
functions and member function pointers.
[endsect]
[section Binding a nonstandard function]
By default, the `bind(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form]
recognizes "ordinary" C++ functions and function pointers. [link
bind.implementation.stdcall Functions that use a different calling convention],
or variable-argument functions such as `std::printf`, do not work. The general
`bind<R>(f, a1, a2, ..., aN)` [link bind.faq.Q_forms form] works with
nonstandard functions.
On some platforms, extern "C" functions, like `std::strcmp`, are not
recognized by the short form of `bind`.
See also [link bind.implementation.stdcall `__stdcall` and `pascal` Support].
[endsect]
[section Binding an overloaded function]
An attempt to bind an overloaded function usually results in an error, as
there is no way to tell which overload was meant to be bound. This is a common
problem with member functions with two overloads, const and non-const, as in
this simplified example:
struct X
{
int& get();
int const& get() const;
};
int main()
{
boost::bind(&X::get, _1);
}
The ambiguity can be resolved manually by casting the (member) function
pointer to the desired type:
int main()
{
boost::bind(static_cast< int const& (X::*) () const >(&X::get), _1);
}
Another, arguably more readable, alternative is to introduce a temporary
variable:
int main()
{
int const& (X::*get) () const = &X::get;
boost::bind(get, _1);
}
[endsect]
[section Modeling STL function object concepts]
The function objects that are produced by `bind` do not model the STL
[@http://www.sgi.com/tech/stl/UnaryFunction.html /Unary Function/] or
[@http://www.sgi.com/tech/stl/BinaryFunction.html /Binary Function/] concepts,
even when the function objects are unary or binary operations, because the
function object types are missing public typedefs `result_type` and
`argument_type` or `first_argument_type` and `second_argument_type`. In cases
where these typedefs are desirable, however, the utility function
`make_adaptable` can be used to adapt unary and binary function objects to
these concepts. This allows unary and binary function objects resulting from
`bind` to be combined with STL templates such as
[@http://en.cppreference.com/w/cpp/utility/functional/unary_negate `std::unary_negate`]
and [@http://en.cppreference.com/w/cpp/utility/functional/binary_negate `std::binary_negate`].
The `make_adaptable` function is defined in [@../../include/boost/bind/make_adaptable.hpp
`<boost/bind/make_adaptable.hpp>`], which must be included explicitly in
addition to [@../../include/boost/bind.hpp `<boost/bind.hpp>`]:
#include <boost/bind/make_adaptable.hpp>
template <class R, class F> ``/unspecified-type/`` make_adaptable(F f);
template<class R, class A1, class F> ``/unspecified-unary-functional-type/`` make_adaptable(F f);
template<class R, class A1, class A2, class F> ``/unspecified-binary-functional-type/`` make_adaptable(F f);
template<class R, class A1, class A2, class A3, class F> ``/unspecified-ternary-functional-type/`` make_adaptable(F f);
template<class R, class A1, class A2, class A3, class A4, class F> ``/unspecified-4-ary-functional-type/`` make_adaptable(F f);
This example shows how to use `make_adaptable` to make a predicate for "is not a space":
typedef char char_t;
std::locale loc("");
const std::ctype<char_t>& ct = std::use_facet<std::ctype<char_t> >(loc);
auto isntspace = std::not1(boost::make_adaptable<bool, char_t>(boost::bind(&std::ctype<char_t>::is, &ct, std::ctype_base::space, _1)));
In this example, `bind` creates the "is a space" (unary) predicate. It is then
passed to `make_adaptable` so that a function object modeling the /Unary
Function/ concept can be created, serving as the argument to
[@http://en.cppreference.com/w/cpp/utility/functional/not1 `std::not1`].
[endsect]
[section `const` in signatures]
Some compilers, including MSVC 6.0 and Borland C++ 5.5.1, have problems with
the top-level `const` in function signatures:
int f(int const);
int main()
{
boost::bind(f, 1); // error
}
Workaround: remove the `const` qualifier from the argument.
[endsect]
[section MSVC specific: `using boost::bind;`]
On MSVC (up to version 7.0), when `boostbind` is brought into scope with an
using declaration:
using boost::bind;
the syntax `bind<R>(f, ...)` does not work. Workaround: either use the
qualified name, `boost::bind`, or use an using directive instead:
using namespace boost;
[endsect]
[section MSVC specific: class templates shadow function templates]
On MSVC (up to version 7.0), a nested class template named `bind` will shadow
the function template `boost::bind`, breaking the `bind<R>(f, ...)`syntax.
Unfortunately, some libraries contain nested class templates named `bind`
(ironically, such code is often an MSVC specific workaround.)
The workaround is to use the alternative `bind(type<R>(), f, ...)` syntax.
[endsect]
[section MSVC specific: `...` in signatures treated as type]
MSVC (up to version 7.0) treats the ellipsis in a variable argument function
(such as `std::printf`) as a type. Therefore, it will accept the (incorrect in
the current implementation) form:
bind(printf, "%s\n", _1);
and will reject the correct version:
bind<int>(printf, "%s\n", _1);
[endsect]
[endsect]

32
doc/mem_fn.qbk Normal file
View File

@@ -0,0 +1,32 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2005 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[library Boost.Member Function
[quickbook 1.6]
[id mem_fn]
[copyright 2001, 2002 Peter Dimov and Multi Media Ltd.]
[copyright 2003-2005 Peter Dimov]
[dirname bind]
[license Distributed under the
[@http://boost.org/LICENSE_1_0.txt Boost Software License,
Version 1.0].
]
]
[template simplesect[title]
[block '''<simplesect><title>'''[title]'''</title>''']]
[template endsimplesect[]
[block '''</simplesect>''']]
[include mem_fn/purpose.qbk]
[include mem_fn/faq.qbk]
[include mem_fn/interface.qbk]
[include mem_fn/implementation.qbk]
[include mem_fn/acknowledgements.qbk]

View File

@@ -0,0 +1,28 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2005 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[section:acknowledgements Acknowledgements]
* Rene Jager's initial suggestion of using traits classes to make `mem_fn`
adapt to user-defined smart pointers inspired the `get_pointer`-based design.
* Numerous improvements were suggested during the formal review period by
Richard Crossley, Jens Maurer, Ed Brey, and others. Review manager was Darin
Adler.
* Steve Anichini pointed out that COM interfaces use `__stdcall`.
* Dave Abrahams modified `bind` and `mem_fn` to support `void` returns on
deficient compilers.
* Daniel Boelzle pointed out that UDK uses `__cdecl`.
This documentation was ported to Quickbook by Agustín Bergé.
[endsect]

53
doc/mem_fn/faq.qbk Normal file
View File

@@ -0,0 +1,53 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2005 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[section:faq Frequently Asked Questions]
[section Can `mem_fn` be used instead of the standard `std::mem_fun[_ref]`
adaptors?]
Yes. For simple uses, `mem_fn` provides additional functionality that the
standard adaptors do not. Complicated expressions that use `std::bind1st`,
`std::bind2nd` or [@http://www.boost.org/doc/libs/1_31_0/libs/compose/index.htm Boost.Compose]
along with the standard adaptors can be rewritten using `boost::bind` that
automatically takes advantage of `mem_fn`.
[endsect]
[section Should I replace every occurence of `std::mem_fun[_ref]` with
`mem_fn` in my existing code?]
No, unless you have good reasons to do so. `mem_fn` is not 100% compatible
with the standard adaptors, although it comes pretty close. In particular,
`mem_fn` does not return objects of type `std::[const_]mem_fun[1][_ref]_t`, as
the standard adaptors do, and it is not possible to fully describe the type of
the first argument using the standard `argument_type` and `first_argument_type`
nested typedefs. Libraries that need adaptable function objects in order to
function might not like `mem_fn`.
[endsect]
[section Does `mem_fn` work with COM methods?]
Yes, if you [link mem_fn.implementation.stdcall `#define BOOST_MEM_FN_ENABLE_STDCALL].
[endsect]
[section Why isn't `BOOST_MEM_FN_ENABLE_STDCALL` defined automatically?]
Non-portable extensions, in general, should default to off to prevent vendor
lock-in. Had `BOOST_MEM_FN_ENABLE_STDCALL` been defined automatically, you
could have accidentally taken advantage of it without realizing that your code
is, perhaps, no longer portable. In addition, it is possible for the default
calling convention to be `__stdcall`, in which case enabling `__stdcall`
support will result in duplicate definitions.
[endsect]
[endsect]

View File

@@ -0,0 +1,70 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2005 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[section:implementation Implementation]
[section Files]
* [@../../include/boost/mem_fn.hpp boost/mem_fn.hpp] (main header)
* [@../../include/boost/bind/mem_fn_cc.hpp boost/bind/mem_fn_cc.hpp] (used by `mem_fn.hpp`, do not include directly)
* [@../../include/boost/bind/mem_fn_vw.hpp boost/bind/mem_fn_vw.hpp] (used by `mem_fn.hpp`, do not include directly)
* [@../../include/boost/bind/mem_fn_template.hpp boost/bind/mem_fn_template.hpp] (used by `mem_fn.hpp`, do not include directly)
* [@../../test/mem_fn_test.cpp libs/bind/test/mem_fn_test.cpp] (test)
* [@../../test/mem_fn_derived_test.cpp libs/bind/test/mem_fn_derived_test.cpp] (test with derived objects)
* [@../../test/mem_fn_fastcall_test.cpp libs/bind/test/mem_fn_fastcall_test.cpp] (test for `__fastcall`)
* [@../../test/mem_fn_stdcall_test.cpp libs/bind/test/mem_fn_stdcall_test.cpp] (test for `__stdcall`)
* [@../../test/mem_fn_void_test.cpp libs/bind/test/mem_fn_void_test.cpp] (test for `void` returns)
[endsect]
[section Dependencies]
* [@boost:/libs/config/config.htm Boost.Config]
[endsect]
[section Number of Arguments]
This implementation supports member functions with up to eight arguments. This
is not an inherent limitation of the design, but an implementation detail.
[endsect]
[section:stdcall `__stdcall`, `__cdecl`, and `__fastcall` Support]
Some platforms allow several types of member functions that differ by their
calling convention (the rules by which the function is invoked: how are
arguments passed, how is the return value handled, and who cleans up the stack
- if any.)
For example, Windows API functions and COM interface member functions use a
calling convention known as `__stdcall`. Borland VCL components use
`__fastcall`. UDK, the component model of OpenOffice.org, uses `__cdecl`.
To use `mem_fn` with `__stdcall` member functions, `#define` the macro
`BOOST_MEM_FN_ENABLE_STDCALL` before including `<boost/mem_fn.hpp>`.
To use `mem_fn` with `__fastcall` member functions, `#define` the macro
`BOOST_MEM_FN_ENABLE_FASTCALL` before including `<boost/mem_fn.hpp>`.
To use `mem_fn` with `__cdecl` member functions, `#define` the macro
`BOOST_MEM_FN_ENABLE_CDECL` before including `<boost/mem_fn.hpp>`.
[*It is best to define these macros in the project options, via `-D` on the
command line, or as the first line in the translation unit (.cpp file) where
`mem_fn` is used.] Not following this rule can lead to obscure errors when a
header includes `mem_fn.hpp` before the macro has been defined.
/[Note:/ this is a non-portable extension. It is not part of the interface./]/
/[Note:/ Some compilers provide only minimal support for the `__stdcall` keyword./]/
[endsect]
[endsect]

133
doc/mem_fn/interface.qbk Normal file
View File

@@ -0,0 +1,133 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2005 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[section:interface Interface]
[section:synopsys Synopsis]
namespace boost
{
template<class T> T * ``[link get_pointer_1 `get_pointer`]``(T * p);
template<class R, class T> ``/unspecified-1/`` ``[link mem_fn_1 `mem_fn`]``(R (T::*pmf) ());
template<class R, class T> ``/unspecified-2/`` ``[link mem_fn_2 `mem_fn`]``(R (T::*pmf) () const);
template<class R, class T> ``/unspecified-2-1/`` ``[link mem_fn_2_1 `mem_fn`]``(R T::*pm);
template<class R, class T, class A1> ``/unspecified-3/`` ``[link mem_fn_3 `mem_fn`]``(R (T::*pmf) (A1));
template<class R, class T, class A1> ``/unspecified-4/`` ``[link mem_fn_4 `mem_fn`]``(R (T::*pmf) (A1) const);
template<class R, class T, class A1, class A2> ``/unspecified-5/`` ``[link mem_fn_5 `mem_fn`]``(R (T::*pmf) (A1, A2));
template<class R, class T, class A1, class A2> ``/unspecified-6/`` ``[link mem_fn_6 `mem_fn`]``(R (T::*pmf) (A1, A2) const);
// implementation defined number of additional overloads for more arguments
}
[endsect]
[section Common requirements]
All /unspecified-N/ types mentioned in the Synopsis are /CopyConstructible/
and /Assignable/. Their copy constructors and assignment operators do not
throw exceptions. /unspecified-N/`::result_type` is defined as the return type
of the member function pointer passed as an argument to `mem_fn` (`R` in the
Synopsis.) /unspecified-2-1/`::result_type` is defined as `R`.
[endsect]
[section `get_pointer`]
[#get_pointer_1]
template<class T> T * get_pointer(T * p)
* /Returns:/ `p`.
* /Throws:/ Nothing.
[endsect]
[section `mem_fn`]
[#mem_fn_1]
template<class R, class T> ``/unspecified-1/`` mem_fn(R (T::*pmf) ())
* /Returns:/ a function object \u03DD such that the expression \u03DD`(t)` is
equivalent to `(t.*pmf)()` when `t` is an l-value of type `T` or derived,
`(get_pointer(t)->*pmf)()` otherwise.
* /Throws:/ Nothing.
[#mem_fn_2]
template<class R, class T> ``/unspecified-2/`` mem_fn(R (T::*pmf) () const)
* /Returns:/ a function object \u03DD such that the expression \u03DD`(t)` is
equivalent to `(t.*pmf)()` when `t` is of type `T` /[/`const`/]/ or derived,
`(get_pointer(t)->*pmf)()` otherwise.
* /Throws:/ Nothing.
[#mem_fn_2_1]
template<class R, class T> ``/unspecified-2-1/`` mem_fn(R T::*pm)
* /Returns:/ a function object \u03DD such that the expression \u03DD`(t)` is
equivalent to `t.*pm` when `t` is of type `T` /[/`const`/]/ or derived,
`get_pointer(t)->*pm` otherwise.
* /Throws:/ Nothing.
[#mem_fn_3]
template<class R, class T, class A1> ``/unspecified-3/`` mem_fn(R (T::*pmf) (A1))
* /Returns:/ a function object \u03DD such that the expression \u03DD`(t, a1)`
is equivalent to `(t.*pmf)(a1)` when `t` is an l-value of type `T` or derived,
`(get_pointer(t)->*pmf)(a1)` otherwise.
* /Throws:/ Nothing.
[#mem_fn_4]
template<class R, class T, class A1> ``/unspecified-4/`` mem_fn(R (T::*pmf) (A1) const)
* /Returns:/ a function object \u03DD such that the expression \u03DD`(t, a1)`
is equivalent to `(t.*pmf)(a1)` when `t` is of type `T` /[/`const`/]/ or derived,
`(get_pointer(t)->*pmf)(a1)` otherwise.
* /Throws:/ Nothing.
[#mem_fn_5]
template<class R, class T, class A1, class A2> ``/unspecified-5/`` mem_fn(R (T::*pmf) (A1, A2))
* /Returns:/ a function object \u03DD such that the expression \u03DD`(t, a1, a2)`
is equivalent to `(t.*pmf)(a1, a2)` when `t` is an l-value of type `T` or derived,
`(get_pointer(t)->*pmf)(a1, a2)` otherwise.
* /Throws:/ Nothing.
[#mem_fn_6]
template<class R, class T, class A1, class A2> ``/unspecified-6/`` mem_fn(R (T::*pmf) (A1, A2) const)
* /Returns:/ a function object \u03DD such that the expression \u03DD`(t, a1, a2)`
is equivalent to `(t.*pmf)(a1, a2)` when `t` is of type `T` /[/`const`/]/ or derived,
`(get_pointer(t)->*pmf)(a1, a2)` otherwise.
* /Throws:/ Nothing.
[endsect]
[endsect]

93
doc/mem_fn/purpose.qbk Normal file
View File

@@ -0,0 +1,93 @@
[/
/ Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
/ Copyright (c) 2003-2005 Peter Dimov
/
/ Distributed under the Boost Software License, Version 1.0. (See
/ accompanying file LICENSE_1_0.txt or copy at
/ http://www.boost.org/LICENSE_1_0.txt)
/]
[section:purpose Purpose]
`boost::mem_fn` is a generalization of the standard functions `std::mem_fun`
and `std::mem_fun_ref`. 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.
`mem_fn` also supports pointers to data members by treating them as functions
taking no arguments and returning a (const) reference to the member.
The purpose of `mem_fn` is twofold. First, it allows users to invoke a member
function on a container with the familiar
std::for_each(v.begin(), v.end(), boost::mem_fn(&Shape::draw));
syntax, even when the container stores smart pointers.
Second, it can be used as a building block by library developers that want to
treat a pointer to member function as a function object. A library might
define an enhanced `for_each` algorithm with an overload of the form:
template<class It, class R, class T> void for_each(It first, It last, R (T::*pmf) ())
{
std::for_each(first, last, boost::mem_fn(pmf));
}
that will allow the convenient syntax:
for_each(v.begin(), v.end(), &Shape::draw);
When documenting the feature, the library author will simply state:
template<class It, class R, class T> void for_each(It first, It last, R (T::*pmf) ());
* /Effects:/ Equivalent to `std::for_each(first, last, boost::mem_fn(pmf))`.
where `boost::mem_fn` can be a link to this page. See the
[@boost:/libs/bind/bind.html documentation of `bind`] for an example.
`mem_fn` takes one argument, a pointer to a member, and returns a function
object suitable for use with standard or user-defined algorithms:
struct X
{
void f();
};
void g(std::vector<X> & v)
{
std::for_each(v.begin(), v.end(), boost::mem_fn(&X::f));
};
void h(std::vector<X *> const & v)
{
std::for_each(v.begin(), v.end(), boost::mem_fn(&X::f));
};
void k(std::vector<boost::shared_ptr<X> > const & v)
{
std::for_each(v.begin(), v.end(), boost::mem_fn(&X::f));
};
The returned function object takes the same arguments as the input member
function plus a "flexible" first argument that represents the object instance.
When the function object is invoked with a first argument `x` that is neither
a pointer nor a reference to the appropriate class (`X` in the example above),
it uses `get_pointer(x)` to obtain a pointer from `x`. Library authors can
"register" their smart pointer classes by supplying an appropriate
`get_pointer` overload, allowing `mem_fn` to recognize and support them.
/[Note:/ `get_pointer` is not restricted to return a pointer. Any object that
can be used in a member function call expression `(x->*pmf)(...)` will work./]/
/[Note:/ the library uses an unqualified call to `get_pointer`. Therefore, it
will find, through argument-dependent lookup, `get_pointer` overloads that are
defined in the same namespace as the corresponding smart pointer class, in
addition to any `boost::get_pointer` overloads./]/
All function objects returned by `mem_fn` expose a `result_type` typedef that
represents the return type of the member function. For data members,
`result_type` is defined as the type of the member.
[endsect]

View File

@@ -1,262 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
<library name="Ref" dirname="ref" id="ref" last-revision="$Date$">
<libraryinfo>
<author>
<firstname>Jaakko</firstname>
<surname>J&auml;rvi</surname>
</author>
<author>
<firstname>Peter</firstname>
<surname>Dimov</surname>
</author>
<author>
<firstname>Douglas</firstname>
<surname>Gregor</surname>
</author>
<author>
<firstname>Dave</firstname>
<surname>Abrahams</surname>
</author>
<copyright>
<year>1999</year>
<year>2000</year>
<holder>Jaakko J&auml;rvi</holder>
</copyright>
<copyright>
<year>2001</year>
<year>2002</year>
<holder>Peter Dimov</holder>
</copyright>
<copyright>
<year>2002</year>
<holder>David Abrahams</holder>
</copyright>
<legalnotice>
<para>Subject to the Boost Software License, Version 1.0. See
accompanying file <filename>LICENSE_1_0.txt</filename> or copy at
<ulink url="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</ulink>.
</para>
</legalnotice>
<librarypurpose>A utility library for passing references to generic functions</librarypurpose>
<librarycategory name="category:higher-order"/>
</libraryinfo>
<title>Boost.Ref</title>
<section id="ref.intro">
<title>Introduction</title>
<using-namespace name="boost"/>
<para>The Ref library is a small library that is useful for passing
references to function templates (algorithms) that would usually
take copies of their arguments. It defines the class template
<code><classname>boost::reference_wrapper&lt;T&gt;</classname></code>,
two functions
<code><functionname>boost::ref</functionname></code> and
<code><functionname>boost::cref</functionname></code> that return
instances of <code>boost::reference_wrapper&lt;T&gt;</code>,
a function <code><functionname>boost::unwrap_ref</functionname></code>
that unwraps a <code>boost::reference_wrapper&lt;T&gt;</code> or
returns a reference to any other type of object, and the
two traits classes
<code><classname>boost::is_reference_wrapper&lt;T&gt;</classname></code>
and
<code><classname>boost::unwrap_reference&lt;T&gt;</classname></code>.</para>
<para>The purpose of
<code>boost::reference_wrapper&lt;T&gt;</code> is to
contain a reference to an object of type T. It is primarily used to
"feed" references to function templates (algorithms) that take their
parameter by value.</para>
<para>To support this usage,
<code>boost::reference_wrapper&lt;T&gt;</code> provides an implicit
conversion to <code>T&amp;</code>. This usually allows the function
templates to work on references unmodified.</para>
<para><code>boost::reference_wrapper&lt;T&gt;</code> is
both CopyConstructible and Assignable (ordinary references are not
Assignable).</para>
<para>The expression <code>boost::ref(x)</code>
returns a
<code>boost::reference_wrapper&lt;X&gt;(x)</code> where X
is the type of x. Similarly,
<code>boost::cref(x)</code> returns a
<code>boost::reference_wrapper&lt;X const&gt;(x)</code>.</para>
<para>The expression <code>boost::unwrap_ref(x)</code>
returns a
<code>boost::unwrap_reference&lt;X&gt;::type&amp;</code> where X
is the type of x.</para>
<para>The expression
<code>boost::is_reference_wrapper&lt;T&gt;::value</code>
is true if T is a <code>reference_wrapper</code>, and
false otherwise.</para>
<para>The type-expression
<code>boost::unwrap_reference&lt;T&gt;::type</code> is T::type if T
is a <code>reference_wrapper</code>, T otherwise.</para>
</section>
<library-reference>
<header name="boost/ref.hpp">
<namespace name="boost">
<class name="reference_wrapper">
<template>
<template-type-parameter name="T"/>
</template>
<purpose>
Contains a reference to an object of type
<computeroutput>T</computeroutput>.
</purpose>
<description>
<para><computeroutput><classname>reference_wrapper</classname></computeroutput>
is primarily used to "feed" references to function templates
(algorithms) that take their parameter by value. It provides
an implicit conversion to
<computeroutput>T&amp;</computeroutput>, which usually allows
the function templates to work on references
unmodified.</para>
</description>
<typedef name="type"><type>T</type></typedef>
<constructor specifiers="explicit">
<parameter name="t">
<paramtype>T&amp;</paramtype>
</parameter>
<effects><simpara>Constructs a
<computeroutput><classname>reference_wrapper</classname></computeroutput>
object that stores a reference to
<computeroutput>t</computeroutput>.</simpara></effects>
<throws><simpara>Does not throw.</simpara></throws>
</constructor>
<method-group name="access">
<method name="conversion-operator" cv="const">
<type>T&amp;</type>
<returns><simpara>The stored reference.</simpara></returns>
<throws><simpara>Does not throw.</simpara></throws>
</method>
<method name="get" cv="const">
<type>T&amp;</type>
<returns><simpara>The stored reference.</simpara></returns>
<throws><simpara>Does not throw.</simpara></throws>
</method>
<method name="get_pointer" cv="const">
<type>T*</type>
<returns><simpara>A pointer to the object referenced by the stored reference.</simpara></returns>
<throws><simpara>Does not throw.</simpara></throws>
</method>
</method-group>
<free-function-group name="constructors">
<function name="ref">
<type>reference_wrapper&lt;T&gt;</type>
<parameter name="t">
<paramtype>T&amp;</paramtype>
</parameter>
<returns><simpara><computeroutput><classname>reference_wrapper</classname>&lt;T&gt;(t)</computeroutput></simpara></returns>
<throws><simpara>Does not throw.</simpara></throws>
</function>
<function name="cref">
<type>reference_wrapper&lt;T const&gt;</type>
<parameter name="t">
<paramtype>T const&amp;</paramtype>
</parameter>
<returns><simpara><computeroutput><classname>reference_wrapper</classname>&lt;T const&gt;(t)</computeroutput></simpara></returns>
<throws><simpara>Does not throw.</simpara></throws>
</function>
</free-function-group>
<free-function-group name="access">
<function name="unwrap_ref">
<type>unwrap_reference&lt;T&gt;::type&amp;</type>
<parameter name="t">
<paramtype>T&amp;</paramtype>
</parameter>
<returns><simpara><computeroutput><classname>unwrap_reference</classname>&lt;T&gt;::type&amp;(t)</computeroutput></simpara></returns>
<throws><simpara>Does not throw.</simpara></throws>
</function>
</free-function-group>
</class>
<class name="is_reference_wrapper">
<template>
<template-type-parameter name="T"/>
</template>
<purpose>Determine if a type <computeroutput>T</computeroutput> is an instantiation of <computeroutput><classname>reference_wrapper</classname></computeroutput>.</purpose>
<description>
<para>The <computeroutput>value</computeroutput> static
constant will be <computeroutput>true</computeroutput> iff the
type <computeroutput>T</computeroutput> is a specialization of
<computeroutput><classname>reference_wrapper</classname></computeroutput>.</para>
</description>
<static-constant name="value">
<type>bool</type>
<default><emphasis>unspecified</emphasis></default>
</static-constant>
</class>
<class name="unwrap_reference">
<template>
<template-type-parameter name="T"/>
</template>
<purpose>Find the type in a <computeroutput><classname>reference_wrapper</classname></computeroutput>.</purpose>
<description>
<para>The typedef <computeroutput>type</computeroutput> is
<computeroutput>T::type</computeroutput> if
<computeroutput>T</computeroutput> is a
<computeroutput><classname>reference_wrapper</classname></computeroutput>,
<computeroutput>T</computeroutput> otherwise.</para>
</description>
<typedef name="type"><type><emphasis>unspecified</emphasis></type></typedef>
</class>
</namespace>
</header>
</library-reference>
<section id="ref.ack">
<title>Acknowledgements</title>
<using-namespace name="boost"/>
<para><functionname>ref</functionname> and <functionname>cref</functionname>
were originally part of the <libraryname>Tuple</libraryname> library
by Jaakko J&auml;rvi. They were "promoted to boost:: status" by
Peter Dimov because they are generally useful. Douglas Gregor and
Dave Abrahams contributed
<classname>is_reference_wrapper</classname> and
<classname>unwrap_reference</classname>. Frank Mori Hess and Ronald
Garcia contributed <functionname>boost::unwrap_ref</functionname></para>
</section>
</library>

View File

@@ -21,6 +21,7 @@
#include <boost/config.hpp>
#include <boost/is_placeholder.hpp>
#include <boost/static_assert.hpp>
namespace boost
{
@@ -33,8 +34,7 @@ template< int I > struct arg
template< class T > arg( T const & /* t */ )
{
// static assert I == is_placeholder<T>::value
typedef char T_must_be_placeholder[ I == is_placeholder<T>::value? 1: -1 ];
BOOST_STATIC_ASSERT( I == is_placeholder<T>::value );
}
};

View File

@@ -29,6 +29,8 @@
#include <boost/bind/arg.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/visit_each.hpp>
#include <boost/core/enable_if.hpp>
#include <boost/core/is_same.hpp>
// Borland-specific bug, visit_each() silently fails to produce code
@@ -859,7 +861,295 @@ public:
// bind_t
#ifndef BOOST_NO_VOID_RETURNS
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
template< class A > struct list_add_cref
{
typedef A const & type;
};
template< class A > struct list_add_cref< A& >
{
typedef A & type;
};
template<class R, class F, class L> class bind_t
{
private:
F f_;
L l_;
public:
typedef typename result_traits<R, F>::type result_type;
typedef bind_t this_type;
bind_t( F f, L const & l ): f_( f ), l_( l ) {}
//
result_type operator()()
{
list0 a;
return l_( type<result_type>(), f_, a, 0 );
}
result_type operator()() const
{
list0 a;
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1> result_type operator()( A1 && a1 )
{
list1< typename list_add_cref<A1>::type > a( a1 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1> result_type operator()( A1 && a1 ) const
{
list1< typename list_add_cref<A1>::type > a( a1 );
return l_(type<result_type>(), f_, a, 0);
}
template<class A1, class A2> result_type operator()( A1 && a1, A2 && a2 )
{
list2< typename list_add_cref<A1>::type, typename list_add_cref<A2>::type > a( a1, a2 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2> result_type operator()( A1 && a1, A2 && a2 ) const
{
list2< typename list_add_cref<A1>::type, typename list_add_cref<A2>::type > a( a1, a2 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3> result_type operator()( A1 && a1, A2 && a2, A3 && a3 )
{
list3<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type
> a( a1, a2, a3 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3> result_type operator()( A1 && a1, A2 && a2, A3 && a3 ) const
{
list3<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type
> a( a1, a2, a3 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3, class A4> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4 )
{
list4<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type,
typename list_add_cref<A4>::type
> a( a1, a2, a3, a4 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3, class A4> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4 ) const
{
list4<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type,
typename list_add_cref<A4>::type
> a( a1, a2, a3, a4 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3, class A4, class A5> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 )
{
list5<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type,
typename list_add_cref<A4>::type,
typename list_add_cref<A5>::type
> a( a1, a2, a3, a4, a5 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3, class A4, class A5> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5 ) const
{
list5<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type,
typename list_add_cref<A4>::type,
typename list_add_cref<A5>::type
> a( a1, a2, a3, a4, a5 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3, class A4, class A5, class A6> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 )
{
list6<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type,
typename list_add_cref<A4>::type,
typename list_add_cref<A5>::type,
typename list_add_cref<A6>::type
> a( a1, a2, a3, a4, a5, a6 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3, class A4, class A5, class A6> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6 ) const
{
list6<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type,
typename list_add_cref<A4>::type,
typename list_add_cref<A5>::type,
typename list_add_cref<A6>::type
> a( a1, a2, a3, a4, a5, a6 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 )
{
list7<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type,
typename list_add_cref<A4>::type,
typename list_add_cref<A5>::type,
typename list_add_cref<A6>::type,
typename list_add_cref<A7>::type
> a( a1, a2, a3, a4, a5, a6, a7 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7 ) const
{
list7<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type,
typename list_add_cref<A4>::type,
typename list_add_cref<A5>::type,
typename list_add_cref<A6>::type,
typename list_add_cref<A7>::type
> a( a1, a2, a3, a4, a5, a6, a7 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 )
{
list8<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type,
typename list_add_cref<A4>::type,
typename list_add_cref<A5>::type,
typename list_add_cref<A6>::type,
typename list_add_cref<A7>::type,
typename list_add_cref<A8>::type
> a( a1, a2, a3, a4, a5, a6, a7, a8 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8 ) const
{
list8<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type,
typename list_add_cref<A4>::type,
typename list_add_cref<A5>::type,
typename list_add_cref<A6>::type,
typename list_add_cref<A7>::type,
typename list_add_cref<A8>::type
> a( a1, a2, a3, a4, a5, a6, a7, a8 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 )
{
list9<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type,
typename list_add_cref<A4>::type,
typename list_add_cref<A5>::type,
typename list_add_cref<A6>::type,
typename list_add_cref<A7>::type,
typename list_add_cref<A8>::type,
typename list_add_cref<A9>::type
> a( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
return l_( type<result_type>(), f_, a, 0 );
}
template<class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> result_type operator()( A1 && a1, A2 && a2, A3 && a3, A4 && a4, A5 && a5, A6 && a6, A7 && a7, A8 && a8, A9 && a9 ) const
{
list9<
typename list_add_cref<A1>::type,
typename list_add_cref<A2>::type,
typename list_add_cref<A3>::type,
typename list_add_cref<A4>::type,
typename list_add_cref<A5>::type,
typename list_add_cref<A6>::type,
typename list_add_cref<A7>::type,
typename list_add_cref<A8>::type,
typename list_add_cref<A9>::type
> a( a1, a2, a3, a4, a5, a6, a7, a8, a9 );
return l_( type<result_type>(), f_, a, 0 );
}
//
template<class A> result_type eval( A & a )
{
return l_( type<result_type>(), f_, a, 0 );
}
template<class A> result_type eval( A & a ) const
{
return l_( type<result_type>(), f_, a, 0 );
}
template<class V> void accept( V & v ) const
{
#if !defined( BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP ) && !defined( __BORLANDC__ )
using boost::visit_each;
#endif
BOOST_BIND_VISIT_EACH( v, f_, 0 );
l_.accept( v );
}
bool compare( this_type const & rhs ) const
{
return ref_compare( f_, rhs.f_, 0 ) && l_ == rhs.l_;
}
};
#elif !defined( BOOST_NO_VOID_RETURNS )
template<class R, class F, class L> class bind_t
{
@@ -875,7 +1165,7 @@ public:
};
#else
#else // no void returns
template<class R> struct bind_t_generator
{
@@ -1680,7 +1970,7 @@ template< class R, class T > struct add_cref< R (T::*) (), 1 >
typedef void type;
};
#if !( defined(__IBMCPP__) && BOOST_WORKAROUND( __IBMCPP__, BOOST_TESTED_AT(600) ) )
#if !defined(__IBMCPP__) || __IBMCPP_FUNC_CV_TMPL_ARG_DEDUCTION
template< class R, class T > struct add_cref< R (T::*) () const, 1 >
{

View File

@@ -34,6 +34,28 @@ template<class R, class T,
return _bi::bind_t<R, F, list_type>(F(f), list_type(a1));
}
template<class Rt2, class R, class T,
class A1>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf0)<R, T>, typename _bi::list_av_1<A1>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (), A1 a1)
{
typedef _mfi::BOOST_BIND_MF_NAME(mf0)<R, T> F;
typedef typename _bi::list_av_1<A1>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1));
}
template<class Rt2, class R, class T,
class A1>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf0)<R, T>, typename _bi::list_av_1<A1>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) () const, A1 a1)
{
typedef _mfi::BOOST_BIND_MF_NAME(cmf0)<R, T> F;
typedef typename _bi::list_av_1<A1>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1));
}
// 1
template<class R, class T,
@@ -58,6 +80,30 @@ template<class R, class T,
return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2));
}
template<class Rt2, class R, class T,
class B1,
class A1, class A2>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf1)<R, T, B1>, typename _bi::list_av_2<A1, A2>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1), A1 a1, A2 a2)
{
typedef _mfi::BOOST_BIND_MF_NAME(mf1)<R, T, B1> F;
typedef typename _bi::list_av_2<A1, A2>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2));
}
template<class Rt2, class R, class T,
class B1,
class A1, class A2>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf1)<R, T, B1>, typename _bi::list_av_2<A1, A2>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1) const, A1 a1, A2 a2)
{
typedef _mfi::BOOST_BIND_MF_NAME(cmf1)<R, T, B1> F;
typedef typename _bi::list_av_2<A1, A2>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2));
}
// 2
template<class R, class T,
@@ -82,6 +128,30 @@ template<class R, class T,
return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3));
}
template<class Rt2, class R, class T,
class B1, class B2,
class A1, class A2, class A3>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf2)<R, T, B1, B2>, typename _bi::list_av_3<A1, A2, A3>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2), A1 a1, A2 a2, A3 a3)
{
typedef _mfi::BOOST_BIND_MF_NAME(mf2)<R, T, B1, B2> F;
typedef typename _bi::list_av_3<A1, A2, A3>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3));
}
template<class Rt2, class R, class T,
class B1, class B2,
class A1, class A2, class A3>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf2)<R, T, B1, B2>, typename _bi::list_av_3<A1, A2, A3>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2) const, A1 a1, A2 a2, A3 a3)
{
typedef _mfi::BOOST_BIND_MF_NAME(cmf2)<R, T, B1, B2> F;
typedef typename _bi::list_av_3<A1, A2, A3>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3));
}
// 3
template<class R, class T,
@@ -106,6 +176,30 @@ template<class R, class T,
return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4));
}
template<class Rt2, class R, class T,
class B1, class B2, class B3,
class A1, class A2, class A3, class A4>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf3)<R, T, B1, B2, B3>, typename _bi::list_av_4<A1, A2, A3, A4>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3), A1 a1, A2 a2, A3 a3, A4 a4)
{
typedef _mfi::BOOST_BIND_MF_NAME(mf3)<R, T, B1, B2, B3> F;
typedef typename _bi::list_av_4<A1, A2, A3, A4>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4));
}
template<class Rt2, class R, class T,
class B1, class B2, class B3,
class A1, class A2, class A3, class A4>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf3)<R, T, B1, B2, B3>, typename _bi::list_av_4<A1, A2, A3, A4>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3) const, A1 a1, A2 a2, A3 a3, A4 a4)
{
typedef _mfi::BOOST_BIND_MF_NAME(cmf3)<R, T, B1, B2, B3> F;
typedef typename _bi::list_av_4<A1, A2, A3, A4>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4));
}
// 4
template<class R, class T,
@@ -130,6 +224,30 @@ template<class R, class T,
return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5));
}
template<class Rt2, class R, class T,
class B1, class B2, class B3, class B4,
class A1, class A2, class A3, class A4, class A5>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf4)<R, T, B1, B2, B3, B4>, typename _bi::list_av_5<A1, A2, A3, A4, A5>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
{
typedef _mfi::BOOST_BIND_MF_NAME(mf4)<R, T, B1, B2, B3, B4> F;
typedef typename _bi::list_av_5<A1, A2, A3, A4, A5>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5));
}
template<class Rt2, class R, class T,
class B1, class B2, class B3, class B4,
class A1, class A2, class A3, class A4, class A5>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf4)<R, T, B1, B2, B3, B4>, typename _bi::list_av_5<A1, A2, A3, A4, A5>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5)
{
typedef _mfi::BOOST_BIND_MF_NAME(cmf4)<R, T, B1, B2, B3, B4> F;
typedef typename _bi::list_av_5<A1, A2, A3, A4, A5>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5));
}
// 5
template<class R, class T,
@@ -154,6 +272,30 @@ template<class R, class T,
return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6));
}
template<class Rt2, class R, class T,
class B1, class B2, class B3, class B4, class B5,
class A1, class A2, class A3, class A4, class A5, class A6>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf5)<R, T, B1, B2, B3, B4, B5>, typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
{
typedef _mfi::BOOST_BIND_MF_NAME(mf5)<R, T, B1, B2, B3, B4, B5> F;
typedef typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6));
}
template<class Rt2, class R, class T,
class B1, class B2, class B3, class B4, class B5,
class A1, class A2, class A3, class A4, class A5, class A6>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf5)<R, T, B1, B2, B3, B4, B5>, typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6)
{
typedef _mfi::BOOST_BIND_MF_NAME(cmf5)<R, T, B1, B2, B3, B4, B5> F;
typedef typename _bi::list_av_6<A1, A2, A3, A4, A5, A6>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6));
}
// 6
template<class R, class T,
@@ -178,6 +320,30 @@ template<class R, class T,
return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7));
}
template<class Rt2, class R, class T,
class B1, class B2, class B3, class B4, class B5, class B6,
class A1, class A2, class A3, class A4, class A5, class A6, class A7>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf6)<R, T, B1, B2, B3, B4, B5, B6>, typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
{
typedef _mfi::BOOST_BIND_MF_NAME(mf6)<R, T, B1, B2, B3, B4, B5, B6> F;
typedef typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7));
}
template<class Rt2, class R, class T,
class B1, class B2, class B3, class B4, class B5, class B6,
class A1, class A2, class A3, class A4, class A5, class A6, class A7>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf6)<R, T, B1, B2, B3, B4, B5, B6>, typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7)
{
typedef _mfi::BOOST_BIND_MF_NAME(cmf6)<R, T, B1, B2, B3, B4, B5, B6> F;
typedef typename _bi::list_av_7<A1, A2, A3, A4, A5, A6, A7>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7));
}
// 7
template<class R, class T,
@@ -202,6 +368,30 @@ template<class R, class T,
return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8));
}
template<class Rt2, class R, class T,
class B1, class B2, class B3, class B4, class B5, class B6, class B7,
class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf7)<R, T, B1, B2, B3, B4, B5, B6, B7>, typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
{
typedef _mfi::BOOST_BIND_MF_NAME(mf7)<R, T, B1, B2, B3, B4, B5, B6, B7> F;
typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8));
}
template<class Rt2, class R, class T,
class B1, class B2, class B3, class B4, class B5, class B6, class B7,
class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf7)<R, T, B1, B2, B3, B4, B5, B6, B7>, typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8)
{
typedef _mfi::BOOST_BIND_MF_NAME(cmf7)<R, T, B1, B2, B3, B4, B5, B6, B7> F;
typedef typename _bi::list_av_8<A1, A2, A3, A4, A5, A6, A7, A8>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8));
}
// 8
template<class R, class T,
@@ -225,3 +415,27 @@ template<class R, class T,
typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
return _bi::bind_t<R, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
}
template<class Rt2, class R, class T,
class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8,
class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(mf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8>, typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8), A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
{
typedef _mfi::BOOST_BIND_MF_NAME(mf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8> F;
typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
}
template<class Rt2, class R, class T,
class B1, class B2, class B3, class B4, class B5, class B6, class B7, class B8,
class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9>
typename boost::enable_if_c<!boost::core::is_same<Rt2, R>::value,
_bi::bind_t<Rt2, _mfi::BOOST_BIND_MF_NAME(cmf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8>, typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type>
>::type BOOST_BIND(R (BOOST_BIND_MF_CC T::*f) (B1, B2, B3, B4, B5, B6, B7, B8) const, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9)
{
typedef _mfi::BOOST_BIND_MF_NAME(cmf8)<R, T, B1, B2, B3, B4, B5, B6, B7, B8> F;
typedef typename _bi::list_av_9<A1, A2, A3, A4, A5, A6, A7, A8, A9>::type list_type;
return _bi::bind_t<Rt2, F, list_type>(F(f), list_type(a1, a2, a3, a4, a5, a6, a7, a8, a9));
}

View File

@@ -25,7 +25,7 @@
namespace
{
#if defined(__BORLANDC__) || defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 400)
#if defined(__BORLANDC__) || defined(__GNUC__) && (__GNUC__ < 4)
static inline boost::arg<1> _1() { return boost::arg<1>(); }
static inline boost::arg<2> _2() { return boost::arg<2>(); }
@@ -38,7 +38,7 @@ static inline boost::arg<8> _8() { return boost::arg<8>(); }
static inline boost::arg<9> _9() { return boost::arg<9>(); }
#elif defined(BOOST_MSVC) || (defined(__DECCXX_VER) && __DECCXX_VER <= 60590031) || defined(__MWERKS__) || \
defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ == 400)
defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ < 2)
static boost::arg<1> _1;
static boost::arg<2> _2;

View File

@@ -1,11 +1,11 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=bind.html">
<meta http-equiv="refresh" content="0; URL=doc/html/bind.html">
</head>
<body>
Automatic redirection failed, please go to
<a href="bind.html">bind.html</a> or
<a href="mem_fn.html">mem_fn.html</a>.
<a href="doc/html/bind.html">doc/html/bind.html</a> or
<a href="doc/html/mem_fn.html">doc/html/mem_fn.html</a>.
</body>
</html>
<!--

View File

@@ -1,14 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0; URL=../bind/mem_fn.html">
<title>Boost.MemberFunction</title>
<meta charset="utf-8">
<meta http-equiv="refresh" content="0; url=doc/html/mem_fn.html">
<style>
body {
background: #fff;
color: #000;
}
a {
color: #00f;
text-decoration: none;
}
</style>
</head>
<body>
Automatic redirection failed, please go to
<a href="../bind/mem_fn.html">../bind/mem_fn.html</a>.&nbsp;<hr>
<p>© Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See accompanying
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or copy
at <a href="http://www.boost.org/LICENSE_1_0.txt">www.boost.org/LICENSE_1_0.txt</a>)</p>
<p>&nbsp;</p>
<p>
Automatic redirection failed, please go to
<a href="doc/html/mem_fn.html">doc/html/mem_fn.html</a>
</p>
<p>
&copy; 2001, 2002 Peter Dimov and Multi Media Ltd.<br>
&copy; 2003-2005 Peter Dimov
</p>
</body>
</html>
</html>

34
meta/libraries.json Normal file
View File

@@ -0,0 +1,34 @@
[
{
"key": "bind",
"name": "Bind",
"authors": [
"Peter Dimov"
],
"description": "boost::bind is a generalization of the standard functions std::bind1st and std::bind2nd. 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.",
"std": [
"tr1"
],
"category": [
"Function-objects"
],
"maintainers": [
"Peter Dimov <pdimov -at- pdimov.com>"
]
},
{
"key": "bind/mem_fn",
"name": "Member Function",
"authors": [
"Peter Dimov"
],
"description": "Generalized binders for function/object/pointers and member functions.",
"documentation": "mem_fn.html",
"std": [
"tr1"
],
"category": [
"Function-objects"
]
}
]

View File

@@ -1,15 +0,0 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=../../doc/html/ref.html">
</head>
<body>
Automatic redirection failed, please go to
<a href="../../doc/html/ref.html">../../doc/html/ref.html</a>
</body>
</html>
<!--
© Copyright Beman Dawes, 2001
Distributed under the Boost Software License, Version 1.0.
See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt
-->

View File

@@ -28,6 +28,9 @@ test-suite "bind"
[ run bind_placeholder_test.cpp ]
[ run bind_rvalue_test.cpp ]
[ run bind_and_or_test.cpp ]
[ run bind_void_test.cpp ]
[ run bind_void_dm_test.cpp ]
[ run bind_void_mf_test.cpp ]
[ run mem_fn_test.cpp ]
[ run mem_fn_void_test.cpp ]
[ run mem_fn_derived_test.cpp ]
@@ -44,4 +47,7 @@ test-suite "bind"
[ run bind_eq3_test.cpp ]
[ run protect_test.cpp ]
[ run mem_fn_unary_addr_test.cpp ]
[ run bind_function2_test.cpp ]
[ run bind_fwd_test.cpp ]
[ run bind_fwd2_test.cpp ]
;

View File

@@ -33,6 +33,12 @@
struct X
{
// SGI-related compilers have odd compiler-synthesized ctors dtors
#ifdef __PATHSCALE__
X() {}
~X() {}
#endif
int operator()()
{
return 17041;

View File

@@ -0,0 +1,118 @@
#include <boost/config.hpp>
//
// bind_function2_test.cpp - regression test
//
// Copyright (c) 2015 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/detail/lightweight_test.hpp>
//
void fv1( int & a )
{
a = 17041;
}
void fv2( int & a, int b )
{
a = b;
}
void fv3( int & a, int b, int c )
{
a = b + c;
}
void fv4( int & a, int b, int c, int d )
{
a = b + c + d;
}
void fv5( int & a, int b, int c, int d, int e )
{
a = b + c + d + e;
}
void fv6( int & a, int b, int c, int d, int e, int f )
{
a = b + c + d + e + f;
}
void fv7( int & a, int b, int c, int d, int e, int f, int g )
{
a = b + c + d + e + f + g;
}
void fv8( int & a, int b, int c, int d, int e, int f, int g, int h )
{
a = b + c + d + e + f + g + h;
}
void fv9( int & a, int b, int c, int d, int e, int f, int g, int h, int i )
{
a = b + c + d + e + f + g + h + i;
}
void function_test()
{
int x = 0;
{
boost::function<void(int&)> fw1 = boost::bind( fv1, _1 );
fw1( x ); BOOST_TEST( x == 17041 );
}
{
boost::function<void(int&, int)> fw2 = boost::bind( fv2, _1, _2 );
fw2( x, 1 ); BOOST_TEST( x == 1 );
}
{
boost::function<void(int&, int, int)> fw3 = boost::bind( fv3, _1, _2, _3 );
fw3( x, 1, 2 ); BOOST_TEST( x == 1+2 );
}
{
boost::function<void(int&, int, int, int)> fw4 = boost::bind( fv4, _1, _2, _3, _4 );
fw4( x, 1, 2, 3 ); BOOST_TEST( x == 1+2+3 );
}
{
boost::function<void(int&, int, int, int, int)> fw5 = boost::bind( fv5, _1, _2, _3, _4, _5 );
fw5( x, 1, 2, 3, 4 ); BOOST_TEST( x == 1+2+3+4 );
}
{
boost::function<void(int&, int, int, int, int, int)> fw6 = boost::bind( fv6, _1, _2, _3, _4, _5, _6 );
fw6( x, 1, 2, 3, 4, 5 ); BOOST_TEST( x == 1+2+3+4+5 );
}
{
boost::function<void(int&, int, int, int, int, int, int)> fw7 = boost::bind( fv7, _1, _2, _3, _4, _5, _6, _7 );
fw7( x, 1, 2, 3, 4, 5, 6 ); BOOST_TEST( x == 1+2+3+4+5+6 );
}
{
boost::function<void(int&, int, int, int, int, int, int, int)> fw8 = boost::bind( fv8, _1, _2, _3, _4, _5, _6, _7, _8 );
fw8( x, 1, 2, 3, 4, 5, 6, 7 ); BOOST_TEST( x == 1+2+3+4+5+6+7 );
}
{
boost::function<void(int&, int, int, int, int, int, int, int, int)> fw9 = boost::bind( fv9, _1, _2, _3, _4, _5, _6, _7, _8, _9 );
fw9( x, 1, 2, 3, 4, 5, 6, 7, 8 ); BOOST_TEST( x == 1+2+3+4+5+6+7+8 );
}
}
int main()
{
function_test();
return boost::report_errors();
}

121
test/bind_fwd2_test.cpp Normal file
View File

@@ -0,0 +1,121 @@
#include <boost/config.hpp>
//
// bind_fwd2_test.cpp - forwarding test for 2 arguments
//
// Copyright (c) 2015 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/bind.hpp>
#include <boost/detail/lightweight_test.hpp>
//
int fv1( int const & a )
{
return a;
}
void fv2_1( int & a, int const & b )
{
a = b;
}
void fv2_2( int const & a, int & b )
{
b = a;
}
int fv2_3( int const & a, int const & b )
{
return a+b;
}
void test()
{
{
int const a = 1;
int r = boost::bind( fv1, _1 )( a );
BOOST_TEST( r == 1 );
}
{
int r = boost::bind( fv1, _1 )( 1 );
BOOST_TEST( r == 1 );
}
{
int a = 1;
int const b = 2;
boost::bind( fv2_1, _1, _2 )( a, b );
BOOST_TEST( a == 2 );
}
{
int a = 1;
boost::bind( fv2_1, _1, _2 )( a, 2 );
BOOST_TEST( a == 2 );
}
{
int const a = 1;
int b = 2;
boost::bind( fv2_2, _1, _2 )( a, b );
BOOST_TEST( b == 1 );
}
{
int b = 2;
boost::bind( fv2_2, _1, _2 )( 1, b );
BOOST_TEST( b == 1 );
}
{
int const a = 1;
int const b = 2;
int r = boost::bind( fv2_3, _1, _2 )( a, b );
BOOST_TEST( r == 3 );
}
{
int const a = 1;
int r = boost::bind( fv2_3, _1, _2 )( a, 2 );
BOOST_TEST( r == 3 );
}
{
int const b = 2;
int r = boost::bind( fv2_3, _1, _2 )( 1, b );
BOOST_TEST( r == 3 );
}
{
int r = boost::bind( fv2_3, _1, _2 )( 1, 2 );
BOOST_TEST( r == 3 );
}
}
int main()
{
test();
return boost::report_errors();
}

250
test/bind_fwd_test.cpp Normal file
View File

@@ -0,0 +1,250 @@
#include <boost/config.hpp>
//
// bind_fwd_test.cpp - forwarding test
//
// Copyright (c) 2015 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/bind.hpp>
#include <boost/detail/lightweight_test.hpp>
//
void fv1( int & a )
{
a = 1;
}
void fv2( int & a, int & b )
{
a = 1;
b = 2;
}
void fv3( int & a, int & b, int & c )
{
a = 1;
b = 2;
c = 3;
}
void fv4( int & a, int & b, int & c, int & d )
{
a = 1;
b = 2;
c = 3;
d = 4;
}
void fv5( int & a, int & b, int & c, int & d, int & e )
{
a = 1;
b = 2;
c = 3;
d = 4;
e = 5;
}
void fv6( int & a, int & b, int & c, int & d, int & e, int & f )
{
a = 1;
b = 2;
c = 3;
d = 4;
e = 5;
f = 6;
}
void fv7( int & a, int & b, int & c, int & d, int & e, int & f, int & g )
{
a = 1;
b = 2;
c = 3;
d = 4;
e = 5;
f = 6;
g = 7;
}
void fv8( int & a, int & b, int & c, int & d, int & e, int & f, int & g, int & h )
{
a = 1;
b = 2;
c = 3;
d = 4;
e = 5;
f = 6;
g = 7;
h = 8;
}
void fv9( int & a, int & b, int & c, int & d, int & e, int & f, int & g, int & h, int & i )
{
a = 1;
b = 2;
c = 3;
d = 4;
e = 5;
f = 6;
g = 7;
h = 8;
i = 9;
}
void test()
{
{
int a = 0;
boost::bind( fv1, _1 )( a );
BOOST_TEST( a == 1 );
}
{
int a = 0;
int b = 0;
boost::bind( fv2, _1, _2 )( a, b );
BOOST_TEST( a == 1 );
BOOST_TEST( b == 2 );
}
{
int a = 0;
int b = 0;
int c = 0;
boost::bind( fv3, _1, _2, _3 )( a, b, c );
BOOST_TEST( a == 1 );
BOOST_TEST( b == 2 );
BOOST_TEST( c == 3 );
}
{
int a = 0;
int b = 0;
int c = 0;
int d = 0;
boost::bind( fv4, _1, _2, _3, _4 )( a, b, c, d );
BOOST_TEST( a == 1 );
BOOST_TEST( b == 2 );
BOOST_TEST( c == 3 );
BOOST_TEST( d == 4 );
}
{
int a = 0;
int b = 0;
int c = 0;
int d = 0;
int e = 0;
boost::bind( fv5, _1, _2, _3, _4, _5 )( a, b, c, d, e );
BOOST_TEST( a == 1 );
BOOST_TEST( b == 2 );
BOOST_TEST( c == 3 );
BOOST_TEST( d == 4 );
BOOST_TEST( e == 5 );
}
{
int a = 0;
int b = 0;
int c = 0;
int d = 0;
int e = 0;
int f = 0;
boost::bind( fv6, _1, _2, _3, _4, _5, _6 )( a, b, c, d, e, f );
BOOST_TEST( a == 1 );
BOOST_TEST( b == 2 );
BOOST_TEST( c == 3 );
BOOST_TEST( d == 4 );
BOOST_TEST( e == 5 );
BOOST_TEST( f == 6 );
}
{
int a = 0;
int b = 0;
int c = 0;
int d = 0;
int e = 0;
int f = 0;
int g = 0;
boost::bind( fv7, _1, _2, _3, _4, _5, _6, _7 )( a, b, c, d, e, f, g );
BOOST_TEST( a == 1 );
BOOST_TEST( b == 2 );
BOOST_TEST( c == 3 );
BOOST_TEST( d == 4 );
BOOST_TEST( e == 5 );
BOOST_TEST( f == 6 );
BOOST_TEST( g == 7 );
}
{
int a = 0;
int b = 0;
int c = 0;
int d = 0;
int e = 0;
int f = 0;
int g = 0;
int h = 0;
boost::bind( fv8, _1, _2, _3, _4, _5, _6, _7, _8 )( a, b, c, d, e, f, g, h );
BOOST_TEST( a == 1 );
BOOST_TEST( b == 2 );
BOOST_TEST( c == 3 );
BOOST_TEST( d == 4 );
BOOST_TEST( e == 5 );
BOOST_TEST( f == 6 );
BOOST_TEST( g == 7 );
BOOST_TEST( h == 8 );
}
{
int a = 0;
int b = 0;
int c = 0;
int d = 0;
int e = 0;
int f = 0;
int g = 0;
int h = 0;
int i = 0;
boost::bind( fv9, _1, _2, _3, _4, _5, _6, _7, _8, _9 )( a, b, c, d, e, f, g, h, i );
BOOST_TEST( a == 1 );
BOOST_TEST( b == 2 );
BOOST_TEST( c == 3 );
BOOST_TEST( d == 4 );
BOOST_TEST( e == 5 );
BOOST_TEST( f == 6 );
BOOST_TEST( g == 7 );
BOOST_TEST( h == 8 );
BOOST_TEST( i == 9 );
}
}
int main()
{
test();
return boost::report_errors();
}

View File

@@ -43,6 +43,11 @@ public:
{
}
// SGI-related compilers have odd compiler-synthesized ctors and dtors
#ifdef __PATHSCALE__
~X() {}
#endif
int state() const
{
return state_;

View File

@@ -0,0 +1,72 @@
#include <boost/config.hpp>
#if defined(BOOST_MSVC)
#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_void_mf_test.cpp - test for bind<void> with member functions
//
// Copyright (c) 2008 Peter Dimov
// Copyright (c) 2014 Agustin Berge
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(push, 3)
#endif
#include <iostream>
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(pop)
#endif
#include <boost/detail/lightweight_test.hpp>
//
struct Z
{
int m;
};
void member_data_test()
{
Z z = { 17041 };
Z * pz = &z;
boost::bind<void>( &Z::m, _1 )( z );
boost::bind<void>( &Z::m, _1 )( pz );
boost::bind<void>( &Z::m, z )();
boost::bind<void>( &Z::m, pz )();
boost::bind<void>( &Z::m, boost::ref(z) )();
Z const cz = z;
Z const * pcz = &cz;
boost::bind<void>( &Z::m, _1 )( cz );
boost::bind<void>( &Z::m, _1 )( pcz );
boost::bind<void>( &Z::m, cz )();
boost::bind<void>( &Z::m, pcz )();
boost::bind<void>( &Z::m, boost::ref(cz) )();
}
int main()
{
member_data_test();
return boost::report_errors();
}

198
test/bind_void_mf_test.cpp Normal file
View File

@@ -0,0 +1,198 @@
#include <boost/config.hpp>
#if defined(BOOST_MSVC)
#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_void_mf_test.cpp - test for bind<void> with member functions
//
// Copyright (c) 2008 Peter Dimov
// Copyright (c) 2014 Agustin Berge
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(push, 3)
#endif
#include <iostream>
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(pop)
#endif
#include <boost/detail/lightweight_test.hpp>
//
long global_result;
//
struct X
{
mutable unsigned int hash;
X(): hash(0) {}
int f0() { f1(17); return 0; }
int g0() const { g1(17); return 0; }
void h0() { h1(17); }
int f1(int a1) { hash = (hash * 17041 + a1) % 32768; return 0; }
int g1(int a1) const { hash = (hash * 17041 + a1 * 2) % 32768; return 0; }
void h1(int a1) { hash = (hash * 17041 + a1 * 2) % 32768; }
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; }
void h2(int a1, int a2) { h1(a1); h1(a2); }
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; }
void h3(int a1, int a2, int a3) { h2(a1, a2); h1(a3); }
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; }
void h4(int a1, int a2, int a3, int a4) { h3(a1, a2, a3); h1(a4); }
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; }
void h5(int a1, int a2, int a3, int a4, int a5) { h4(a1, a2, a3, a4); h1(a5); }
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; }
void h6(int a1, int a2, int a3, int a4, int a5, int a6) { h5(a1, a2, a3, a4, a5); h1(a6); }
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; }
void h7(int a1, int a2, int a3, int a4, int a5, int a6, int a7) { h6(a1, a2, a3, a4, a5, a6); h1(a7); }
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 h8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { h7(a1, a2, a3, a4, a5, a6, a7); h1(a8); }
};
void member_function_test()
{
using namespace boost;
X x;
// 0
bind<void>(&X::f0, &x)();
bind<void>(&X::f0, ref(x))();
bind<void>(&X::g0, &x)();
bind<void>(&X::g0, x)();
bind<void>(&X::g0, ref(x))();
bind<void>(&X::h0, x)();
// 1
bind<void>(&X::f1, &x, 1)();
bind<void>(&X::f1, ref(x), 1)();
bind<void>(&X::g1, &x, 1)();
bind<void>(&X::g1, x, 1)();
bind<void>(&X::g1, ref(x), 1)();
bind<void>(&X::h1, x, 1)();
// 2
bind<void>(&X::f2, &x, 1, 2)();
bind<void>(&X::f2, ref(x), 1, 2)();
bind<void>(&X::g2, &x, 1, 2)();
bind<void>(&X::g2, x, 1, 2)();
bind<void>(&X::g2, ref(x), 1, 2)();
bind<void>(&X::h2, x, 1, 2)();
// 3
bind<void>(&X::f3, &x, 1, 2, 3)();
bind<void>(&X::f3, ref(x), 1, 2, 3)();
bind<void>(&X::g3, &x, 1, 2, 3)();
bind<void>(&X::g3, x, 1, 2, 3)();
bind<void>(&X::g3, ref(x), 1, 2, 3)();
bind<void>(&X::h3, x, 1, 2, 3)();
// 4
bind<void>(&X::f4, &x, 1, 2, 3, 4)();
bind<void>(&X::f4, ref(x), 1, 2, 3, 4)();
bind<void>(&X::g4, &x, 1, 2, 3, 4)();
bind<void>(&X::g4, x, 1, 2, 3, 4)();
bind<void>(&X::g4, ref(x), 1, 2, 3, 4)();
bind<void>(&X::h4, x, 1, 2, 3, 4)();
// 5
bind<void>(&X::f5, &x, 1, 2, 3, 4, 5)();
bind<void>(&X::f5, ref(x), 1, 2, 3, 4, 5)();
bind<void>(&X::g5, &x, 1, 2, 3, 4, 5)();
bind<void>(&X::g5, x, 1, 2, 3, 4, 5)();
bind<void>(&X::g5, ref(x), 1, 2, 3, 4, 5)();
bind<void>(&X::h5, x, 1, 2, 3, 4, 5)();
// 6
bind<void>(&X::f6, &x, 1, 2, 3, 4, 5, 6)();
bind<void>(&X::f6, ref(x), 1, 2, 3, 4, 5, 6)();
bind<void>(&X::g6, &x, 1, 2, 3, 4, 5, 6)();
bind<void>(&X::g6, x, 1, 2, 3, 4, 5, 6)();
bind<void>(&X::g6, ref(x), 1, 2, 3, 4, 5, 6)();
bind<void>(&X::h6, x, 1, 2, 3, 4, 5, 6)();
// 7
bind<void>(&X::f7, &x, 1, 2, 3, 4, 5, 6, 7)();
bind<void>(&X::f7, ref(x), 1, 2, 3, 4, 5, 6, 7)();
bind<void>(&X::g7, &x, 1, 2, 3, 4, 5, 6, 7)();
bind<void>(&X::g7, x, 1, 2, 3, 4, 5, 6, 7)();
bind<void>(&X::g7, ref(x), 1, 2, 3, 4, 5, 6, 7)();
bind<void>(&X::h7, x, 1, 2, 3, 4, 5, 6, 7)();
// 8
bind<void>(&X::f8, &x, 1, 2, 3, 4, 5, 6, 7, 8)();
bind<void>(&X::f8, ref(x), 1, 2, 3, 4, 5, 6, 7, 8)();
bind<void>(&X::g8, &x, 1, 2, 3, 4, 5, 6, 7, 8)();
bind<void>(&X::g8, x, 1, 2, 3, 4, 5, 6, 7, 8)();
bind<void>(&X::g8, ref(x), 1, 2, 3, 4, 5, 6, 7, 8)();
bind<void>(&X::h8, x, 1, 2, 3, 4, 5, 6, 7, 8)();
BOOST_TEST( x.hash == 23558 );
}
int main()
{
member_function_test();
return boost::report_errors();
}

139
test/bind_void_test.cpp Normal file
View File

@@ -0,0 +1,139 @@
#include <boost/config.hpp>
#if defined(BOOST_MSVC)
#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_void_test.cpp - test for bind<void>
//
// Copyright (c) 2008 Peter Dimov
// Copyright (c) 2014 Agustin Berge
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#include <boost/bind.hpp>
#include <boost/ref.hpp>
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(push, 3)
#endif
#include <iostream>
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(pop)
#endif
#include <boost/detail/lightweight_test.hpp>
//
long global_result;
long f_0()
{
return global_result = 17041L;
}
long f_1(long a)
{
return global_result = a;
}
long f_2(long a, long b)
{
return global_result = a + 10 * b;
}
long f_3(long a, long b, long c)
{
return global_result = a + 10 * b + 100 * c;
}
long f_4(long a, long b, long c, long d)
{
return global_result = a + 10 * b + 100 * c + 1000 * d;
}
long f_5(long a, long b, long c, long d, long e)
{
return global_result = 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 global_result = 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 global_result = 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 global_result = 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 global_result = 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<void>(f_0)(i), (global_result == 17041L)) );
BOOST_TEST( (bind<void>(f_1, _1)(i), (global_result == 1L)) );
BOOST_TEST( (bind<void>(f_2, _1, 2)(i), (global_result == 21L)) );
BOOST_TEST( (bind<void>(f_3, _1, 2, 3)(i), (global_result == 321L)) );
BOOST_TEST( (bind<void>(f_4, _1, 2, 3, 4)(i), (global_result == 4321L)) );
BOOST_TEST( (bind<void>(f_5, _1, 2, 3, 4, 5)(i), (global_result == 54321L)) );
BOOST_TEST( (bind<void>(f_6, _1, 2, 3, 4, 5, 6)(i), (global_result == 654321L)) );
BOOST_TEST( (bind<void>(f_7, _1, 2, 3, 4, 5, 6, 7)(i), (global_result == 7654321L)) );
BOOST_TEST( (bind<void>(f_8, _1, 2, 3, 4, 5, 6, 7, 8)(i), (global_result == 87654321L)) );
BOOST_TEST( (bind<void>(f_9, _1, 2, 3, 4, 5, 6, 7, 8, 9)(i), (global_result == 987654321L)) );
}
//
struct Y
{
short operator()(short & r) const { return global_result = ++r; }
int operator()(int a, int b) const { return global_result = a + 10 * b; }
long operator() (long a, long b, long c) const { return global_result = a + 10 * b + 100 * c; }
void operator() (long a, long b, long c, long d) const { global_result = a + 10 * b + 100 * c + 1000 * d; }
};
void function_object_test()
{
using namespace boost;
short i(6);
int const k = 3;
BOOST_TEST( (bind<void>(Y(), ref(i))(), (global_result == 7)) );
BOOST_TEST( (bind<void>(Y(), ref(i))(), (global_result == 8)) );
BOOST_TEST( (bind<void>(Y(), i, _1)(k), (global_result == 38)) );
BOOST_TEST( (bind<void>(Y(), i, _1, 9)(k), (global_result == 938)) );
BOOST_TEST( (bind<void>(Y(), i, _1, 9, 4)(k), (global_result == 4938)) );
}
int main()
{
function_test();
function_object_test();
return boost::report_errors();
}

View File

@@ -39,128 +39,128 @@ struct X
// 0
int mf0_1() { return 0; }
int mf0_2() { return 0; }
int mf0_2() { return 1; }
int cmf0_1() const { return 0; }
int cmf0_2() const { return 0; }
int cmf0_2() const { return 1; }
void mf0v_1() {}
void mf0v_2() {}
void mf0v_2() { static int x; ++x; }
void cmf0v_1() const {}
void cmf0v_2() const {}
void cmf0v_2() const { static int x; ++x; }
// 1
int mf1_1(int) { return 0; }
int mf1_2(int) { return 0; }
int mf1_2(int) { return 1; }
int cmf1_1(int) const { return 0; }
int cmf1_2(int) const { return 0; }
int cmf1_2(int) const { return 1; }
void mf1v_1(int) {}
void mf1v_2(int) {}
void mf1v_2(int) { static int x; ++x; }
void cmf1v_1(int) const {}
void cmf1v_2(int) const {}
void cmf1v_2(int) const { static int x; ++x; }
// 2
int mf2_1(int, int) { return 0; }
int mf2_2(int, int) { return 0; }
int mf2_2(int, int) { return 1; }
int cmf2_1(int, int) const { return 0; }
int cmf2_2(int, int) const { return 0; }
int cmf2_2(int, int) const { return 1; }
void mf2v_1(int, int) {}
void mf2v_2(int, int) {}
void mf2v_2(int, int) { static int x; ++x; }
void cmf2v_1(int, int) const {}
void cmf2v_2(int, int) const {}
void cmf2v_2(int, int) const { static int x; ++x; }
// 3
int mf3_1(int, int, int) { return 0; }
int mf3_2(int, int, int) { return 0; }
int mf3_2(int, int, int) { return 1; }
int cmf3_1(int, int, int) const { return 0; }
int cmf3_2(int, int, int) const { return 0; }
int cmf3_2(int, int, int) const { return 1; }
void mf3v_1(int, int, int) {}
void mf3v_2(int, int, int) {}
void mf3v_2(int, int, int) { static int x; ++x; }
void cmf3v_1(int, int, int) const {}
void cmf3v_2(int, int, int) const {}
void cmf3v_2(int, int, int) const { static int x; ++x; }
// 4
int mf4_1(int, int, int, int) { return 0; }
int mf4_2(int, int, int, int) { return 0; }
int mf4_2(int, int, int, int) { return 1; }
int cmf4_1(int, int, int, int) const { return 0; }
int cmf4_2(int, int, int, int) const { return 0; }
int cmf4_2(int, int, int, int) const { return 1; }
void mf4v_1(int, int, int, int) {}
void mf4v_2(int, int, int, int) {}
void mf4v_2(int, int, int, int) { static int x; ++x; }
void cmf4v_1(int, int, int, int) const {}
void cmf4v_2(int, int, int, int) const {}
void cmf4v_2(int, int, int, int) const { static int x; ++x; }
// 5
int mf5_1(int, int, int, int, int) { return 0; }
int mf5_2(int, int, int, int, int) { return 0; }
int mf5_2(int, int, int, int, int) { return 1; }
int cmf5_1(int, int, int, int, int) const { return 0; }
int cmf5_2(int, int, int, int, int) const { return 0; }
int cmf5_2(int, int, int, int, int) const { return 1; }
void mf5v_1(int, int, int, int, int) {}
void mf5v_2(int, int, int, int, int) {}
void mf5v_2(int, int, int, int, int) { static int x; ++x; }
void cmf5v_1(int, int, int, int, int) const {}
void cmf5v_2(int, int, int, int, int) const {}
void cmf5v_2(int, int, int, int, int) const { static int x; ++x; }
// 6
int mf6_1(int, int, int, int, int, int) { return 0; }
int mf6_2(int, int, int, int, int, int) { return 0; }
int mf6_2(int, int, int, int, int, int) { return 1; }
int cmf6_1(int, int, int, int, int, int) const { return 0; }
int cmf6_2(int, int, int, int, int, int) const { return 0; }
int cmf6_2(int, int, int, int, int, int) const { return 1; }
void mf6v_1(int, int, int, int, int, int) {}
void mf6v_2(int, int, int, int, int, int) {}
void mf6v_2(int, int, int, int, int, int) { static int x; ++x; }
void cmf6v_1(int, int, int, int, int, int) const {}
void cmf6v_2(int, int, int, int, int, int) const {}
void cmf6v_2(int, int, int, int, int, int) const { static int x; ++x; }
// 7
int mf7_1(int, int, int, int, int, int, int) { return 0; }
int mf7_2(int, int, int, int, int, int, int) { return 0; }
int mf7_2(int, int, int, int, int, int, int) { return 1; }
int cmf7_1(int, int, int, int, int, int, int) const { return 0; }
int cmf7_2(int, int, int, int, int, int, int) const { return 0; }
int cmf7_2(int, int, int, int, int, int, int) const { return 1; }
void mf7v_1(int, int, int, int, int, int, int) {}
void mf7v_2(int, int, int, int, int, int, int) {}
void mf7v_2(int, int, int, int, int, int, int) { static int x; ++x; }
void cmf7v_1(int, int, int, int, int, int, int) const {}
void cmf7v_2(int, int, int, int, int, int, int) const {}
void cmf7v_2(int, int, int, int, int, int, int) const { static int x; ++x; }
// 8
int mf8_1(int, int, int, int, int, int, int, int) { return 0; }
int mf8_2(int, int, int, int, int, int, int, int) { return 0; }
int mf8_2(int, int, int, int, int, int, int, int) { return 1; }
int cmf8_1(int, int, int, int, int, int, int, int) const { return 0; }
int cmf8_2(int, int, int, int, int, int, int, int) const { return 0; }
int cmf8_2(int, int, int, int, int, int, int, int) const { return 1; }
void mf8v_1(int, int, int, int, int, int, int, int) {}
void mf8v_2(int, int, int, int, int, int, int, int) {}
void mf8v_2(int, int, int, int, int, int, int, int) { static int x; ++x; }
void cmf8v_1(int, int, int, int, int, int, int, int) const {}
void cmf8v_2(int, int, int, int, int, int, int, int) const {}
void cmf8v_2(int, int, int, int, int, int, int, int) const { static int x; ++x; }
};