Boost logo

Boost :

Subject: Re: [boost] phoenix::bind
From: Peter Dimov (pdimov_at_[hidden])
Date: 2008-09-29 12:58:51

Eric Niebler:

> OK, OK, you got me. Even for Phoenix, the rules are not simple. Phoenix
> captures by value *when it can* (except for arrays, which are by
> reference, I think), or when the user specifies by-ref with phoenix::ref.
> But the decision is based on object's type, not on how the object is used
> in the expression, as it is with boost.lambda. Consider that with
> boost.lambda:
> int ii = 0;
> ii += _1; // ii captured by reference here ...
> _1 += ii; // ... but ii captured by value here

Right. As with std::cout, this is being done for usability reasons. The
demand for op= to capture its left operand by value is nonexistent.

I do not necessarily claim that Lambda is right. After all, boost::bind
deliberately captures by value in situations in which it knows that by-ref
is more common.

Normally, I'd state that both Lambda and Phoenix need to pick one over the
other and stick with it. But there is a problem with this as well in that it
could affect the eventual compatibility with boost::bind.

boost::bind dutifully propagates its constness to the bound object and its
arguments. In bind( f, a )(), f and a are non-const, because bind(f,a)
isn't. Phoenix doesn't. It always "constifies" its contents. This is a good
thing for

    ii += _1

because it allows it to fail.

Const propagation is less of an issue in Phoenix because it has true local
variables. With boost::bind and a suitably defined f, one can do

    boost::bind( f, 0, 0, _1 )

to approximate a lambda with two local variables, initially 0, and one
argument. Phoenix doesn't need such tricks. But the question needs to be
considered, and a balance has to be struck.

(It's also possible to only constify the left side of op=, which is also a
bit of a hack, but would be a net usability win.)

Boost list run by bdawes at, gregod at, cpdaniel at, john at