On 5/4/2013 7:30 PM, Jonathan M Davis wrote:
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.

I meant exactly what you said: "and not know that it was effectively a no-op".

Reply via email to