Boost logo

Boost :

Subject: Re: [boost] phoenix::bind
From: Joel de Guzman (joel_at_[hidden])
Date: 2008-09-29 22:51:24


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

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk