Const ref and rvalues again...
martin
kinke at libero.it
Fri Nov 9 08:26:21 PST 2012
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').
Now please go ahead and shoot. :)
More information about the Digitalmars-d
mailing list