Discussion: Rvalue refs and a Move construtor for D
kinke
noone at nowhere.com
Thu Sep 5 20:29:55 UTC 2019
On Thursday, 5 September 2019 at 19:38:57 UTC, Suleyman wrote:
> His initial point about the advantage of rvalue still remains
> unchallenged.
>
> Example:
> ```
> void foo(@rvalue ref S value, int n = 0)
> {
> if (n > 32)
> return;
>
> foo(__move(value), n + 1);
> }
>
> [...]
>
> The whole program only calls the destructor for the lvalue, and
> only once. You need a competitive alternative.
I know that rvalue refs in the language would enable the same
thing, but that's exactly what I'd like to avoid to keep things
nice and simple. When using some 3rd-party code, you don't want
to depend on them providing the required (and ugly) rvalue ref
signatures when coming along with a complex 1KB struct. And there
are no rvalue refs in existing code as of now, so existing code
bases would have to be uglified to exploit the potential.
This is more or less how I'd imagine it at this time:
struct S
{
// only called for: `auto s = move(rhs)`
moveThis(ref S rhs);
~this();
// only called for: `s = move(rhs)`
opMoveAssign(ref S rhs);
}
// forwarding `auto ref` parameter - unchanged:
void callee(ref S lvalArg);
void callee(S rvalArg);
void foo()(auto ref S s) // either `ref S` reference or `S` value
{
// ref case: pass along `s` ref
// value case: `move(s)` (no actual moving, rather imagine
forwarding an rvalue ref when coming from C++)
callee(forward(s));
}
void foo(S param);
// NEW D ABI: non-PODs and large PODs passed by ref, not on the
stack.
// Already the case for D on Win64 and how C++ seems to do it
generally.
// Also new: `foo` doesn't destruct `param` anymore, that is to
be done by the
// caller. That's how C++ does it and currently a hurdle for C++
interop.
void caller(S s)
{
foo(S()); // construct temporary and pass by ref, then
destruct
foo(s); // copy-construct temporary and pass by ref,
then destruct
foo(move(s)); // pass `s` directly by ref, then destruct and
reset to S.init
}
Potential problems:
* Don't access the moved lvalue anywhere else in the statement.
* An lvalue moved in an argument expression is destructed twice,
i.e., 2 times at the same address.
* Cannot represent C++ functions with rvalue refs (except for
move ctor and move-assignment operator).
* Some more, I'm sure. ;)
More information about the Digitalmars-d
mailing list