Boost logo

Boost :

Subject: Re: [boost] [GSoC][Phoenix3] Regarding mutability of arguments passed to phoenix expressions
From: Joel de Guzman (djowel_at_[hidden])
Date: 2010-06-11 11:35:18

On 6/11/10 11:12 PM, Eric Niebler wrote:
> On 4/28/2010 1:26 PM, Eric Niebler wrote:
>> On 4/28/2010 10:19 AM, Mathias Gaunard wrote:
>>> Thomas Heller wrote:
>>>> Regarding arguments to phoenix expressions there are two
>>>> possibilities. The first is: Arguments are mutable. The current
>>>> phoenix is implemented to be able to this.
>> We now have lambdas in C++0x. IMO, we should be paying attention to
>> the default semantics of lambdas which, IIRC, accept their arguments
>> by value(?), and have special syntax for accepting their arguments
>> by reference. Someone should correct me if I got that backwards. In
>> the long haul, I think this will satisfy the Principle of Least
>> Surprise.
> Following up on this ... I was conflating lambda arguments with captured
> variables that appear in the lambda body. I just looked over the draft
> standard, and variables are captured by reference by default and need
> special syntax to capture them by value. 5.1.2/14-15:

That's interesting. Is there a rationale?

>> 14 An entity is captured by copy if it is implicitly captured and the
>> capture-default is = or if it is explicitly captured with a capture
>> that does not include an&. For each entity captured by copy, an
>> unnamed nonstatic data member is declared in the closure type. The
>> declaration order of these members is unspecified. The type of such a
>> data member is the type of the corresponding captured entity if the
>> entity is not a reference to an object, or the referenced type
>> otherwise. [ Note: if the captured entity is a reference to a
>> function, the corresponding data member is also a reference to a
>> function. —end note ]
>> 15 An entity is captured by reference if it is implicitly or
>> explicitly captured but not captured by copy. It is unspecified
>> whether additional unnamed non-static data members are declared in
>> the closure type for entities captured by reference.
> This seems pretty clear to me, so I think Phoenix has it backwards wrt
> variable capture. I find it interesting that functions are called out as
> a special case, but not arrays or abstract types. Presumably it's simply
> an error to try to capture these by value, but the standard could simply
> As for the lambda arguments, Phoenix can take no guidance from the
> standard since the built-in lambdas require you to define an argument
> list, making them monomorphic. We could aim for consistency with the
> capture behavior and pass by reference, or be consistent with std::bind
> which uses rvalue refs and perfect forwarding (darn), or TR1 bind and
> boost::bind which accepts parameters by value.
> Given the choices, I think pass-by-value makes the most sense.

So do I, but why do you think does it make the most sense?
It would be good to explore this further. I am all for consistency,
but now I'm less sure about which way to go. By value is safer.
How about by reference? What's the advantage there? rvalue refs
and perfect forwarding is ideal, but what about older compilers
and compatibility? What are the disadvantages of each approach?
I'm still biased towards by-value, but then again, I'd like to
hear the pros and cons of each approach.


Joel de Guzman

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