diff --git a/bind.html b/bind.html index 36ea678..74110c5 100644 --- a/bind.html +++ b/bind.html @@ -60,6 +60,7 @@
[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 noncopyable, expensive to copy, or contains state; of
+ course, in this case the programmer is expected to ensure that the function
+ object is not destroyed while it's still being used.
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 @@ -285,21 +307,23 @@ std::for_each(v.begin(), v.end(), bind(apply<void>(), _1, 5)); evaluation, use protect(bind(f, ...)).
For convenience, the function objects produced by bind overload the - logical not operator ! and the relational operators ==, - !=, <, <=, >, - >=.
+ 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 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.
+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" );
+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:
@@ -362,10 +386,12 @@ void connect() }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 problem.
+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); @@ -373,17 +399,17 @@ void connect()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: +
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 (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 only recently been resolved.] +
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.
Frequently Asked Questions
Why doesn't this compile?
@@ -528,6 +554,37 @@ int main() recognized by the short form of bind.See also "__stdcall" and "pascal" Support.
+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 ); +} +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: @@ -859,7 +916,7 @@ namespace by Jaakko Järvi;