mirror of
https://github.com/boostorg/bind.git
synced 2025-08-02 14:24:29 +02:00
Ported bind documentation to BoostBook
This commit is contained in:
30
doc/Jamfile.v2
Normal file
30
doc/Jamfile.v2
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# 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 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
|
||||||
|
;
|
35
doc/bind.qbk
Normal file
35
doc/bind.qbk
Normal 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]
|
46
doc/bind/acknowledgements.qbk
Normal file
46
doc/bind/acknowledgements.qbk
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
[/
|
||||||
|
/ 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.
|
||||||
|
|
||||||
|
[endsect]
|
70
doc/bind/examples.qbk
Normal file
70
doc/bind/examples.qbk
Normal 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
99
doc/bind/faq.qbk
Normal 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]
|
98
doc/bind/implementation.qbk
Normal file
98
doc/bind/implementation.qbk
Normal 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
216
doc/bind/interface.qbk
Normal 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
37
doc/bind/limitations.qbk
Normal 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
273
doc/bind/purpose.qbk
Normal 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(42), _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]
|
268
doc/bind/troubleshooting.qbk
Normal file
268
doc/bind/troubleshooting.qbk
Normal 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]
|
Reference in New Issue
Block a user