Settling rvalue to (const) ref parameter binding once and for all
Manu
turkeyman at gmail.com
Sat Nov 10 03:05:28 PST 2012
Hear hear!
I have dreams at night that look exactly like this proposal! :)
I think I had one just last night, and woke up with a big grin on my face...
> 2) rvalues: prefer pass-by-value (moving: argument allocated
directly on callee's stack (parameter) vs. pointer/reference
indirection implied by pass-by-ref)
Is this actually possible?
Does the C/C++ ABI support such an action? GDC and LDC use the C ABI
verbatim, so can this work, or will they have to, like usual, allocate on
the caller's stack, and pass the ref through. I don't really see a
significant disadvantage to that regardless.
On 9 November 2012 20:05, martin <kinke at libero.it> wrote:
> Hi guys,
>
> I hope you don't mind that I'm starting yet another thread about this
> tedious issue, but I think the other threads are too clogged.
>
> Let me summarize my (final, I guess) proposal. I think it makes sense to
> compare it to C++ in order to anticipate and hopefully invalidate (mainly
> Andrei's) objections.
>
> parameter type | lvalue | rvalue
> | C++ D | C++ D
> ------------------------|-----**--------|------------
> T | copy copy | copy move
> T& / ref T | ref ref | n/a n/a
> out T (D only) | ref | n/a
> T&& (C++ only) | n/a | move
> auto ref T (D only) (*) | ref | ref
> ------------------------|-----**--------|------------
> const T | copy copy | copy move
> const T& / const ref T | ref ref | ref ref (*)
> const T&& (C++ only) | n/a | move
>
> (*): proposed additions
>
> For lvalues in both C++ and D, there are 2 options: either copy the
> argument (pass-by-value) or pass it by ref. There's no real difference
> between both languages except for D's additional 'out' keyword and, with
> the proposed 'auto ref' syntax, an (imo negligible) ambiguity between 'ref
> T' and 'auto ref T' in D.
>
> Rvalues are a different topic though. There are 3 possibilites in general:
> copy, move and pass by ref. Copying rvalue arguments does not make sense -
> the argument won't be used by the caller after the invokation, so a copy is
> redundant and hurts performance. D corrects this design flaw of C++ (which
> had to introduce rvalue refs to add move semantics on top of the default
> copy semantics) and therefore only supports moving instead. C++
> additionally supports pass-by-ref of rvalues to const refs, but not to
> mutable refs. I propose to allow pass-by-ref to both const (identical
> syntax as C++, it's perfectly safe and logical) and mutable refs (new
> syntax with 'auto ref' to emphasize that the parameter may be an rvalue
> reference, with related consequences such as potentially missing side
> effects).
>
> Regarding the required overloading priorities for the proposed additions
> to work properly, I propose:
> 1) lvalues: prefer pass-by-ref
> so: ref/out T -> auto ref T (*) -> const ref T -> (const) T
> - const lvalues: const ref T -> (const) T
> - mutable lvalues: ref/out T -> auto ref T (*) -> const ref T ->
> (const) T
> 2) rvalues: prefer pass-by-value (moving: argument allocated
> directly on callee's stack (parameter) vs. pointer/reference
> indirection implied by pass-by-ref)
> so: (const) T -> auto ref T (*) -> const ref T (*)
>
> Finally, regarding templates, I'm in favor of dropping the current 'auto
> ref' semantics and propose to simply adopt the proposed semantics for
> consistency and simplicity and to avoid excessive code bloating. That
> shouldn't break existing code I hope (unless parameters have been denoted
> with 'const auto ref T', which would need to be changed to 'const ref T').
>
> ---
>
> Before posting concerns about a perceived unsafety of binding rvalues to
> 'const ref' parameters, please try to find a plausible argument as to why
> the following is currently allowed:
>
> void foo(const ref T x);
> if (condition)
> {
> T tmp;
> foo(tmp);
> } // destruction of tmp
>
> but the following shortcut, eliminating 3 lines (depending on code
> formatting preferences ;)) and avoiding the pollution of the local
> namespace with a 'tmp' variable, shouldn't be allowed:
>
> if (condition)
> foo(T()); // rvalue destructed immediately after the call
>
> ---
>
> Let me also illustrate a deterministic allocation/destruction scheme for
> the compiler implementation/language specification:
>
> void foo(auto/const ref T a, auto/const ref T b);
>
> foo(T(), T());
> /* order:
> 1) allocate argument a on caller's stack
> 2) allocate argument b on caller's stack
> 3) invoke foo() and pass the argument addresses (refs)
> 4) destruct b
> 5) destruct a
> */
>
> I guess something like that is covered by the C++ specification for
> binding rvalues to const refs.
>
> ---
>
> Now please go ahead and shoot. :)
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20121110/12482bb2/attachment-0001.html>
More information about the Digitalmars-d
mailing list