+
+
+Files
+
+
+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.
+
+
+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::bind1st(std::ptr_fun(f), 5)(x);
+
+
+
+bind covers the functionality of std::bind2nd as well:
+
+
+
+std::bind2nd(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)
+
+
+
+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);
+
+
+Using bind with function objects
+
+
+Any function object can be passed as a first argument to bind, but the
+syntax is a bit different. 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 in the general case):
+
+
+
+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
+
+
+
+[Note: when, hopefully,
+
+function template default arguments become part of C++,
+bind will no longer require the explicit specification of the return type
+when the function object defines result_type.]
+
+
+Using bind with member function pointers
+
+
+Pointers to member functions are not function objects, because they do not
+support operator(). For convenience, bind accepts member function
+pointers as its first argument, and the behavior is as if
+boost::mem_fn has been used to convert the member
+function 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.
+
+
+[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().
+
+
+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 nested subexpressions are evaluated when the function object is called. 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 an
+exception to the nesting rules. A nested bind expression passed
+to bind as a first argument is not treated differently from
+any other function object:
+
+
+
+int x = 4;
+
+template<class F> void test(F f)
+{
+ bind(f, 5)(x);
+}
+
+int g(int, int);
+
+int main()
+{
+ test(bind(g, _1, 8)); // g(5, 8) and not g(x, 8)(5)
+}
+
+
+Example: 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)));
+}
+
+
+Example: using bind with Boost.Function
+
+
+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);
+}
+
+
+Limitations
+
+
+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, known as the
+"forwarding function problem."
+
+
+
+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.
+
+
+
+An oft-proposed "solution" to this problem is to add an overload:
+
+
+
+template<class T> void f(T & t);
+template<class T> void f(T const & t);
+
+
+
+Unfortunately, this (a) requires providing 512 overloads for nine arguments
+and (b) does not actually work for const arguments, both l- and r-values,
+since the two templates produce the exact same signature and cannot be
+partially ordered.
+
+
+
+[Note: this is a dark corner of the language, and the
+
+corresponding issue has not been resolved yet.]
+
+
+Interface
+
+Synopsis
+
+
+namespace boost
+{
+
+// no arguments
+
+template<class R, class F> implementation-defined-1 bind(F f);
+
+template<class R> implementation-defined-2 bind(R (*f) ());
+
+// one argument
+
+template<class R, class F, class A1> implementation-defined-3 bind(F f, A1 a1);
+
+template<class R, class B1, class A1> implementation-defined-4 bind(R (*f) (B1), A1 a1);
+
+template<class R, class T, class A1> implementation-defined-5 bind(R (T::*f) (), A1 a1);
+
+template<class R, class T, class A1> implementation-defined-6 bind(R (T::*f) () const, A1 a1);
+
+// two arguments
+
+template<class R, class F, class A1, class A2> implementation-defined-7 bind(F f, A1 a1, A2 a2);
+
+template<class R, class B1, class B2, class A1, class A2> implementation-defined-8 bind(R (*f) (B1, B2), A1 a1, A2 a2);
+
+template<class R, class T, class B1, class A1, class A2> implementation-defined-9 bind(R (T::*f) (B1), A1 a1, A2 a2);
+
+template<class R, class T, class B1, class A1, class A2> implementation-defined-10 bind(R (T::*f) (B1) const, A1 a1, A2 a2);
+
+// implementation defined number of additional overloads for more arguments
+
+}
+
+namespace
+{
+
+implementation-defined-placeholder-type-1 _1;
+
+implementation-defined-placeholder-type-2 _2;
+
+implementation-defined-placeholder-type-3 _3;
+
+// implementation defined number of additional placeholder definitions
+
+}
+
+
+Common requirements
+
+
+All implementation-defined-N types returned by bind are
+CopyConstructible. implementation-defined-N::result_type is defined as
+the return type of implementation-defined-N::operator().
+
+
+
+All implementation-defined-placeholder-N types are
+CopyConstructible. Their copy constructors do not throw exceptions.
+
+
+Common definitions
+
+
+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.
+
+
+
+bind
+
+
+
+
+Returns: a function object λ such that the expression
+λ(v1, v2, ..., vm) is equivalent to f(),
+implicitly converted to R.
+
+
+Throws: Nothing unless the copy constructor of F throws an exception.
+
+
+
+
+
+Returns: a function object λ such that the expression
+λ(v1, v2, ..., vm) is equivalent to f().
+
+
+Throws: Nothing.
+
+
+
+
+
+Returns: a function object λ such that the expression
+λ(v1, v2, ..., vm) is equivalent to
+f(µ(a1, v1, v2, ..., vm)),
+implicitly converted to R.
+
+
+Throws: Nothing unless the copy constructors of F and A1 throw an exception.
+
+
+
+
+
+Returns: a function object λ such that the expression
+λ(v1, v2, ..., vm) is equivalent to
+f(µ(a1, v1, v2, ..., vm)).
+
+
+Throws: Nothing unless the copy constructor of A1 throws an exception.
+
+
+
+
+
+Effects: equivalent to bind<R>(boost::mem_fn(f), a1);
+
+
+
+
+
+Effects: equivalent to bind<R>(boost::mem_fn(f), a1);
+
+
+
+
+
+Returns: a function object λ such that the expression
+λ(v1, v2, ..., vm) is equivalent to
+f(µ(a1, v1, v2, ..., vm), µ(a2, v1, v2, ..., vm)),
+implicitly converted to R.
+
+
+Throws: Nothing unless the copy constructors of F, A1 and A2 throw an exception.
+
+
+
+
+
+Returns: a function object λ such that the expression
+λ(v1, v2, ..., vm) is equivalent to
+f(µ(a1, v1, v2, ..., vm), µ(a2, v1, v2, ..., vm)).
+
+
+Throws: Nothing unless the copy constructors of A1 and A2 throw an exception.
+
+
+
+
+
+Effects: equivalent to bind<R>(boost::mem_fn(f), a1, a2);
+
+
+
+
+
+Effects: equivalent to bind<R>(boost::mem_fn(f), a1, a2);
+
+
+Implementation
+
+
+This implementation supports function objects with up to nine arguments.
+This is an implementation detail, not an inherent limitation of the
+design.
+
+
+Void returns
+
+
+The following C++ code:
+
+
+
+void f();
+
+void g()
+{
+ return f();
+}
+
+
+
+is legal; in fact it was deliberately made legal in order to support
+forwarding functions that return void.
+
+
+
+Unfortunately, some compilers have not caught up with the C++ Standard yet
+and do not allow void returns. This implementation of bind will not
+work for function pointers, member function pointers or function objects that
+return void if the compiler does not support the feature. A possible
+workaround is to change the return type of the function object in question
+from void to int and return a dummy value of 0.
+
+
+MSVC specific problems and workarounds
+
+
+Microsoft Visual C++ (up to version 7.0) does not fully support the
+bind<R>(...)
+syntax required by the library when arbitrary function objects are bound.
+The first problem is that when boost::bind is brought into scope
+with an using declaration:
+
+
+
+using boost::bind;
+
+
+
+the syntax above does not work. Workaround: either use the qualified name,
+boost::bind, or use an using directive instead:
+
+
+
+using namespace boost;
+
+
+
+The second problem is that some libraries contain nested class templates
+named bind (ironically, such code is often an MSVC specific
+workaround.) Due to some quirks with the parser, such a class template
+breaks the bind<R>(...) syntax, even when the name bind
+is fully qualified. You may try to patch the library in question or contact
+its author/maintainer. The other option is to define the macro
+BOOST_BIND to something other than bind (before the inclusion of
+<boost/bind.hpp>) and use this identifier throughout your code
+wherever you'd normally use bind.
+
+
+
+[Note: BOOST_BIND is not a general renaming mechanism. It is not part of the
+interface, and is not guaranteed to work on other compilers, or persist between
+library versions. In short, don't use it unless you absolutely have to.]
+
+
+Visitor support
+
+
+[Note: this is an experimental feature. It may evolve over time
+when other libraries start to exploit it; or it may be removed altogether if
+no other library needs it. It is not part of the interface.]
+
+
+
+For better integration with other libraries, the function objects returned by
+bind define a member function
+
+
+
+template<class Visitor> void accept(Visitor & v);
+
+
+
+that applies v, as a function object, to its internal state. Using
+accept is implementation-specific and not intended for end users.
+
+
+
+See bind_test_4.cpp for an example.
+
+
+Acknowledgements
+
+
+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.
+
+
+
Copyright © 2001 by Peter Dimov and Multi Media
+Ltd. Permission to copy, use, modify, sell and distribute this document is
+granted provided this copyright notice appears in all copies. This document
+is provided "as is" without express or implied warranty, and with
+no claim as to its suitability for any purpose.
+
+ |
+
+