Rvalue references - The resolution

Jonathan M Davis jmdavisProg at gmx.com
Sat May 4 19:30:21 PDT 2013


On Saturday, May 04, 2013 19:04:21 Walter Bright wrote:
> On 5/4/2013 6:44 PM, Jonathan M Davis wrote:
> > On Saturday, May 04, 2013 20:37:36 Andrei Alexandrescu wrote:
> >> On 5/4/13 7:31 PM, Walter Bright wrote:
> >>> On 5/4/2013 3:51 PM, w0rp wrote:
> >>>> Does all of this also mean that a
> >>>> function with a ref parameter will automagically work with r-values?
> >>> 
> >>> Yes.
> >> 
> >> This is new to me. My understanding is that the discussed design
> >> addresses safety, and leaves the rvalue discussion for a future
> >> iteration.
> > 
> > That is definitely where things were when we ended the discussion on
> > Wednesday night. Walter favored making ref accept rvalues, but we never
> > agreed on that. Manu was still in favor of scop ref (and David Nadlinger
> > agreed with him IIRC), and you and I were arguing for auto ref to
> > designate that a function accepts rvalues. We all agreed on the bounds
> > check solution for @safety, but we explicitly tabled the discussion about
> > accepting rvalues, because it was getting late, and we'd already been
> > discussing it / arguing about it for quite some time. So, unless further
> > discussion occurred after that which I missed, there is still no
> > agreement on how to handle having a parameter accept both lvalues and
> > rvalues by ref.
> 
> That wasn't my understanding. I thought we agreed that since rvalues would
> be copied to locals, and then the issue was one of escaping local
> references.

The @safety issue is one of escaping local references, but Andrei and I were 
arguing that it's a maintenance issue for ref to always accept rvalues. If ref 
does not accept rvalues, then you can look at a function signature like

auto foo(ref int i);

and know that it's intended to alter its argument. However, if ref accepted 
rvalues, you couldn't know that anymore. People would be using ref all over 
the place for the efficiency gain - just like they do with const ref in C++ - so 
the fact that a parameter was ref would mean nothing about how it was used. 
So, you could see code like

[5, 6, 7].popFrontN(5);

and not know that it was effectively a no-op (in this case, it's fairly 
obvious, but if you're not already familiar with the function, it generally 
wouldn't be).

However, if we had an attribute which explicitly designated that a function 
accepted both rvalues and lvalues (which is what auto ref was originally 
supposed to do as Andrei proposed it), then if you saw

auto foo(ref int i);
auto bar(auto ref int i);

then you could be reasonably certain that foo was intending to alter its 
arguments and bar was not. And if you want the full guarantee that bar _can't_ 
alter its arguments, you use const

auto bar(auto ref const int i);

But given how restrictive D's const is, we can't really go with C++'s solution 
of const& for that. However, auto ref is then very similar to C++'s const&, 
except that it doesn't require const to do it (and it's @safe thanks to the 
new @safety solution for ref).

So, the primary difference between ref and auto ref would then be simply that 
auto ref accepted rvalues and ref wouldn't (though, the difference would be 
somewhat greater with templates, since in that case, it generates different 
templates for lvalues and rvalues in order to accept both, whereas the non-
templated version would effectively create a local variable to assign the 
rvalue to so that it could be passed to the function as an lvalue). But the 
distinction between ref and auto ref is very important when trying to 
understand what code does and therefore will have a definite impact on how 
maintainable code is.

> We did explicitly defer discussion about what happens with "nop" rvalue
> conversions.

I'm not sure what you mean by nop rvalue conversions, at least not by name.

- Jonathan M Davis


More information about the Digitalmars-d mailing list