DIP 1016 and const ref parameters

Jonathan M Davis newsgroup.d at jmdavisprog.com
Thu Jun 20 00:30:35 UTC 2019


On Wednesday, June 19, 2019 4:45:04 PM MDT XavierAP via Digitalmars-d-learn 
wrote:
> On Wednesday, 19 June 2019 at 21:06:48 UTC, XavierAP wrote:
> > Now with an rvalue returned from get, interesting, no copy.
> > Still, I wonder what really happened. Again, moving between
> > stacks would still be work. And a different optimization can
> > explain this non copy, for example inlining.
>
> My guess as to what may be happening (I've never used a
> disassembler and I wasn't planning on starting today yet) is
> simple. The rvalue returned by get() is possibly not popped out
> from the stack, but rather left in the same place as sum() is
> called on it. This is actually optimum, but hardly an
> optimization, rather it's the easiest and least effort for the
> compiler. Again this would mean no moving -- which is good,
> because moving is work.
>
> And also, this doesn't work in the general case. If parameters
> are by value, everything works perfect when I pass rvalues (but
> we already knew that, not answering my question); however if I
> pass lvalues they will be copied every time.
>
> So my question is open... what about const ref rvalue parameters?
>
> Or another possible optimization: in case the function is
> declared with const parameters (not ref), lvalues can be accessed
> by ref as an optimization; and rvalues can use the same trick
> they do now. As a consequence, no unnecessary copies ever --
> thanks to const. This is even better because I don't have to type
> so many ref, which were never part of the algorithm but baby
> instructions for the dumb compiler (const & everywhere is one of
> the ugliest and most annoying things in C++).

If you want to know the current state of passing rvalues by ref, watch
Andrei's talk. If you've already watched it, then you know what the current
plan is, and I don't understand what you're trying to find out. Until the
DIP is implemented, if you want a function to accept lvalues by ref and
still accept rvalues, then use auto ref. e.g.

void foo(T)(auto ref T t) {...}

The refness of the parameter will be inferred based on whether it's given an
lvalue or rvalue. If a templated function doesn't fit the bill, then you
have to overload the function based on ref. e.g.

void foo(ref T t) {...}

void foo(T t) {...}

Either way, const has nothing to do with any of this. You're free to mark a
ref or auto ref parameter as const, but it has nothing to do with whether
rvalues are accepted, and it will never have anything to do with whether
rvalues are accepted. D's const is far too restrictive for it to make any
sense to base rvalue stuff on it like they do in C++. The DIP has nothing do
with const and everything to do with ref.

Regardless, the refness of a parameter is part of its type, and I'd be very
surprised if it were ever changed so that any parameter that was not marked
with ref was ever ref. Certainly, it wouldn't work for the refness to change
based on the argument, because the refness is part of the function's type
and determines how the generated code passes the argument. The closest that
we have and likely ever will have to the same function accepting by ref and
by value is auto ref, and that only works, because it's a template, and
different versions of the function are generated based on what's passed.
It's never the case that the exact same function takes some values by ref
and some not. Even once ref parameters accept rvalues, they're going to have
to be turned into lvalues underneath the hood for that to work. It just
won't require you to do it explicitly anymore, and the lifetime of the
generated lvalue will be the same as any temporary.

Ultimately, if you want a function to accept both rvalues and lvalues as
efficiently as posible, just templatize it and use auto ref.

- Jonathan M Davis





More information about the Digitalmars-d-learn mailing list