From aef08dd0cdf5098281c5a1003e7c05a0abeb0843 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Tue, 19 Feb 2008 15:09:10 +0000 Subject: [PATCH] Fix #1642. [SVN r43321] --- bind.html | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/bind.html b/bind.html index f5bcea0..f60cab0 100644 --- a/bind.html +++ b/bind.html @@ -307,21 +307,22 @@ std::for_each(v.begin(), v.end(), bind(apply<void>(), _1, 5));

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.

+

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" );

+

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:

@@ -384,10 +385,12 @@ void connect() }

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 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);
@@ -395,17 +398,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?