
Peter Dimov wrote:
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.
Alright, let's put it to a vote then. Here's my vote: Capture expressions by value: +1 Capture special objects by ref (e.g. cout, endl, arrays): +1 In addition, I'd like to provide a customization point for allowing certain objects to be captured by reference, cout, endl, arrays being provided out of the box. Something like: template <> struct capture_by_ref<MyClass> : mpl::true_ {};
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.
That's a nice trick! That can be quite useful on certain occasions.
Phoenix doesn't need such tricks. But the question needs to be considered, and a balance has to be struck.
What do you think would be a good balance? Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net