From: Brian McNamara (lorgon_at_[hidden])
Date: 2004-02-19 13:31:40
On Thu, Feb 19, 2004 at 03:46:01PM +0200, Peter Dimov wrote:
> Brian McNamara wrote:
> > That is, you cannot write "app" so that both calls here:
> > int f(int);
> > int g(int&);
> > int x;
> > ...
> > app(_,3)(f);
> > app(_,x)(g);
> > work properly. It's impossible.
> Let's see if I get this right:
> #include <boost/bind.hpp>
> #include <boost/bind/apply.hpp>
> #include <iostream>
> int f(int x)
> std::cout << "f(" << x << ")\n";
> return x;
> int g(int & x)
> std::cout << "g(" << x << ")\n";
> return ++x;
> int main()
> int x = 2;
> // app(_, 3)(f);
> boost::bind( boost::apply<int>(), _1, 3 )(f);
> // app(_, x)(g);
> boost::bind( boost::apply<int>(), _1, x )(g);
> boost::bind( boost::apply<int>(), _1, boost::ref(x) )(g);
> You are saying that in the general case we can't decide between the last two
> lines, so we shouldn't support references.
In a nutshell, yes.
> But I'm not sure that this is true. It seems to me that the rule is
> that I should use ref(x) if my x will outlive the function object, as in
> the above, and a plain x otherwise, and it will "just work".
This is not the rule I desire (though it is one possible way to go).
I don't like this rule because it is deciding "whether to reference or
not" based on the argument, rather than on the function. That is, in
the case of
I don't want to pass "x" by reference simply because it appears be be a
non-transient object with sufficient lifetime. "f" doesn't need a
reference, so I shouldn't be creating one.
In any case, the question of "if my x will outlive the function object"
is non-trivial. Consider
// assume h is a functoid with signature int h(int&,int)
// assume l is a list<int>
int x = 1;
l = map( h(x), l ); // note that "h(x)" means "h(x,_)"
Does "x" outlive the function object? Is it reasonable to pass "x" by
The answer to both is no. Functional programming idioms often create
less-than-obvious lifetime issues. In the case above, the function
object outlives "x", because "l" is a lazy list and it stores the
function object so that list elements can later be computed on-demand.
> > boost::lambda's "solution" is to always take reference parameters;
> > this is why we have
> > (_1 + _2)( 5, 7 ) // no, not 12--it's illegal
> No, not correct. In the bind equivalent to app(_, x)(f), x is always copied
> by default. It's f that is passed by reference.
Right, sorry; I was unclear. The function objects created via lambda
expressions always take non-const reference parameters. In contrast,
FC++ function objects always take const reference parameters.
(And, in both libraries, partial application makes a copy of the bound
(Is this right?)
-- -Brian McNamara (lorgon_at_[hidden])
Boost list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk