...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Copyright © 2001, 2002 Peter Dimov and Multi Media Ltd.
Copyright © 2003-2008 Peter Dimov
Distributed under the Boost Software License, Version 1.0.
Table of Contents
bind(f, ...)
and
bind<R>(f, ...)
?bind(f, ...)
bind<R>(f, ...)
const
in signaturesusing boost::bind;
...
in signatures treated
as type
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.
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::ref
and 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);
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);
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::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>(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
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::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()
.
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
for an example that demonstrates how to use bind
to achieve similar functionality to 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 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 protect.hpp
contains an implementation of protect
.
To protect
a bind function
object from evaluation, use protect(bind(f, ...))
.
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
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))); }
class button
{
public:
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);
}
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 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.
See the dedicated Troubleshooting section.
Probably because you used the general bind<R>(f, ...)
syntax, thereby instructing bind
to not "inspect" f to detect arity and return type errors.
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.
Yes, if you #define
BOOST_BIND_ENABLE_STDCALL
.
An alternative is to treat the function as a generic
function object and use the bind<R>(f, ...)
syntax.
Yes, if you #define
BOOST_BIND_ENABLE_PASCAL
.
An alternative is to treat the function as a generic
function object and use the bind<R>(f, ...)
syntax.
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 generic
function object and use the bind<R>(f, ...)
syntax.
Non-portable extensions, in general, should default to off to prevent vendor
lock-in. Had the 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.
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 }
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 }
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)
.
The bind(f, a1, a2,
..., aN)
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.
The bind<R>(f, a1, a2,
..., aN)
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.
By default, the bind(f, a1, a2,
..., aN)
form
recognizes "ordinary" C++ functions and function pointers. 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)
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 __stdcall
and pascal
Support.
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); }
The function objects that are produced by bind
do not model the STL Unary
Function or 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 std::unary_negate
and std::binary_negate
.
The make_adaptable
function
is defined in <boost/bind/make_adaptable.hpp>
,
which must be included explicitly in addition to <boost/bind/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 std::not1
.
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.
On MSVC (up to version 7.0), when boost::bind
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;
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.
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);
namespace boost { // no arguments template<class R, class F> unspecified-1bind
(F f); template<class F> unspecified-1-1bind
(F f); template<class R> unspecified-2bind
(R (*f) ()); // one argument template<class R, class F, class A1> unspecified-3bind
(F f, A1 a1); template<class F, class A1> unspecified-3-1bind
(F f, A1 a1); template<class R, class B1, class A1> unspecified-4bind
(R (*f) (B1), A1 a1); template<class R, class T, class A1> unspecified-5bind
(R (T::*f) (), A1 a1); template<class R, class T, class A1> unspecified-6bind
(R (T::*f) () const, A1 a1); template<class R, class T, class A1> unspecified-6-1bind
(R T::*f, A1 a1); // two arguments template<class R, class F, class A1, class A2> unspecified-7bind
(F f, A1 a1, A2 a2); template<class F, class A1, class A2> unspecified-7-1bind
(F f, A1 a1, A2 a2); template<class R, class B1, class B2, class A1, class A2> unspecified-8bind
(R (*f) (B1, B2), A1 a1, A2 a2); template<class R, class T, class B1, class A1, class A2> unspecified-9bind
(R (T::*f) (B1), A1 a1, A2 a2); template<class R, class T, class B1, class A1, class A2> unspecified-10bind
(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 }
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.
The function μ(x, v1,
v2, ..., vm)
, where m
is a nonnegative integer, is defined as:
x.get()
,
when x
is of type 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.
template<class R, class F> unspecified-1 bind(F f)
(v1, v2, ..., vm)
is equivalent to f()
,
implicitly converted to R
.
F
throws an exception.
template<class F> unspecified-1-1 bind(F f)
bind<typename
F::result_type,
F>(f)
.
f
via
other means as an extension, without relying on the result_type
member.
template<class R> unspecified-2 bind(R (*f) ())
(v1, v2, ..., vm)
is equivalent to f()
.
template<class R, class F, class A1> unspecified-3 bind(F f, A1 a1)
(v1, v2, ..., vm)
is equivalent to f(
μ(a1, v1, v2, ..., vm))
,
implicitly converted to R
.
F
or A1
throw an exception.
template<class F, class A1> unspecified-3-1 bind(F f, A1 a1)
bind<typename
F::result_type,
F,
A1>(f, a1)
.
f
via
other means as an extension, without relying on the result_type
member.
template<class R, class B1, class A1> unspecified-4 bind(R (*f) (B1), A1 a1)
(v1, v2, ..., vm)
is equivalent to f(
μ(a1, v1, v2, ..., vm))
.
A1
throws an exception.
template<class R, class T, class A1> unspecified-5 bind(R (T::*f) (), A1 a1)
bind<R>(
boost::mem_fn
(f), a1)
.
template<class R, class T, class A1> unspecified-6 bind(R (T::*f) () const, A1 a1)
bind<R>(
boost::mem_fn
(f), a1)
.
template<class R, class T, class A1> unspecified-6-1 bind(R T::*f, A1 a1)
bind<R>(
boost::mem_fn
(f), a1)
.
template<class R, class F, class A1, class A2> unspecified-7 bind(F f, A1 a1, A2 a2)
(v1, v2, ..., vm)
is equivalent to f(
μ(a1, v1, v2, ..., vm),
μ(a2, v1, v2, ..., vm))
,
implicitly converted to R
.
F
, A1
or A2
throw an exception.
template<class F, class A1, class A2> unspecified-7-1 bind(F f, A1 a1, A2 a2)
bind<typename
F::result_type,
F,
A1,
A2>(f, a1, a2)
.
f
via
other means as an extension, without relying on the result_type
member.
template<class R, class B1, class B2, class A1, class A2> unspecified-8 bind(R (*f) (B1, B2), A1 a1, A2 a2)
(v1, v2, ..., vm)
is equivalent to f(
μ(a1, v1, v2, ..., vm),
μ(a2, v1, v2, ..., vm))
.
A1
or A2
throw an exception.
template<class R, class T, class B1, class A1, class A2> unspecified-9 bind(R (T::*f) (B1), A1 a1, A2 a2)
bind<R>(
boost::mem_fn
(f), a1, a2)
.
template<class R, class T, class B1, class A1, class A2> unspecified-10 bind(R (T::*f) (B1) const, A1 a1, A2 a2)
bind<R>(
boost::mem_fn
(f), a1, a2)
.
Implementations are allowed to provide additional bind
overloads in order to support more arguments or different function pointer
variations.
bind.hpp
, do not include directly)
bind.hpp
, do not include directly)
bind.hpp
, do not include directly)
_1
, _2
, ... _9
placeholders)
apply
helper function
object)
protect
helper function)
make_adaptable
helper
function)
__stdcall
functions)
__stdcall
member functions)
__fastcall
functions)
__fastcall
member functions)
This implementation supports function objects with up to nine arguments. This is an implementation detail, not an inherent limitation of the design.
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/bind.hpp>
.
To use bind
with __stdcall
member functions, #define
the macro BOOST_MEM_FN_ENABLE_STDCALL
before including <boost/bind/bind.hpp>
.
To use bind
with __fastcall
functions, #define
the macro BOOST_BIND_ENABLE_FASTCALL
before including <boost/bind/bind.hpp>
.
To use bind
with __fastcall
member functions, #define
the macro BOOST_MEM_FN_ENABLE_FASTCALL
before including <boost/bind/bind.hpp>
.
To use bind
with pascal
functions, #define
the macro BOOST_BIND_ENABLE_PASCAL
before including <boost/bind/bind.hpp>
.
To use bind
with __cdecl
member functions, #define
the macro BOOST_MEM_FN_ENABLE_CDECL
before including <boost/bind/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.]
Function objects returned by bind
support the experimental and undocumented, as of yet, visit_each
enumeration interface.
See bind_visitor.cpp for an example.
Earlier efforts that have influenced the library design:
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 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ärvi.
Dave Abrahams fixed a MSVC-specific conflict between bind
and the 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é.