Boost logo

Boost :

From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2008-04-10 18:17:52


On Thu, Apr 10, 2008 at 12:00 PM, Eric Niebler
<eric_at_[hidden]> wrote:
> shunsuke wrote:
> > Eric Niebler wrote:
> >>> As shown above, lvalue/rvalue-ness doesn't guarantee the complete safety.
> >> I think your argument is specious.
> >
> > I just show a counter-example.
> > It might not be a real use case, though.
> > I think
> >
> > int i;
> > /* perform elaborate calculations for i. */
> > return make_tuple(rvalue(i));
> >
> > seems odd.
>
> I actually agree. I've looked again at fusion::make_tuple and I see I
> misremembered its behavior. It always stores arguments by value unless
> the argument is a reference_wrapper. That seems reasonable, even in C++0x.
>
> So maybe I'm coming around to thinking that function objects that do
> something different with lvalues and rvalues are always a bad idea, even
> in C++0x. Not sure yet what the implications are for proto transforms.

Yeah, I have the same intuition about treating them differently. I
haven't looked closely enough at proto to appreciate the dangling
reference issue that led to the differentiation between lvalues and
rvalues, but my gut tells me that if at all possible it's better not
to worry about whether the references are to temporaries/rvalues or
not; instead, focus on the copyability and modifiability of function
parameters...

For C++03 call-by-reference functions, rvalue arguments bound to
references are never copied and are never modifiable.

For C++0x call-by-reference functions, rvalue arguments bound to
references are never copied, but with the new rvalue references, they
can be modifiable.

For both standards, of course, call-by-value functions always copy
their arguments and may modify the copies.

So, following fusion::tuple's example in a way, by adopting a
call-by-value convention for all functions there would be no more
references to dangle. Then the problem is copying objects. However,
that's exactly the problem reference_wrapper solves - it allows the
caller to make a call-by-value function act as if it's
call-by-reference, and it puts the responsibility of managing the
lifetime/validity of the reference in the hands of the caller. Under
this scenario, reference_wrappers would not be a convention for
representing lvalue/rvalue-ness but simply referenceness; i.e. whether
the parameter is copied. Something along these lines would be safe, at
least as safe as fusion::tuple, and would be forward compatible.
However, in order to take advantage of the new C++0x rvalue
references, Boost.Ref would need to be extended with new functions
along the lines of Shunsuke's rvalue(), say rref() and crref(), which
would be the rvalue counterparts of ref() and cref() - i.e. they would
generate reference_wrappers with implicit conversion to T&&. I don't
think this would require an entirely new wrapper template, but it
might.

FWIW, those are just some thoughts. I can't judge whether this would
be suitable for proto or not. Thinking about this, though, it seems to
me that extending boost ref to handle rvalue references should
probably be under consideration as more C++0x compilers come to life.

Daniel


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