Move Constructors - Converting Lvalues to Rvalues
Walter Bright
newshound2 at digitalmars.com
Wed Oct 2 18:00:29 UTC 2024
On 10/1/2024 1:06 PM, Timon Gehr wrote:
> I think in case we did go the function route, I think any implementation of
> `move` that is much more complex than the following is a failure:
>
> ```d
> auto move(T)(@moved T arg)=>arg;
> ```
The major difference between @move and __rvalue is the former is attached to the
parameter, and the latter is attached to the argument. This might seem a
distinction without a difference, but this has large implications with how
overloading works.
For example, how do we distinguish a move constructor from a copy constructor?
```
this(ref S); // copy constructor
this(S); // move constructor
S s = t; // calls copy constructor (lvalue)
S s = f(); // calls move constructor (rvalue)
```
The current overloading rules work out of the box, an rvalue goes for the move
constructor, and an lvalue goes to the copy constructor.
The problem here is when I want to move t into s. How do I get it to call the
move constructor?
```
S move(ref S s) { return s; } // convert argument from lvalue to rvalue
S s = move(t);
```
This works, however, it creates a copy of s and then moves the copy! There needs
to be a way to tell the compiler to use the move construct, hence:
```
S s = __rvalue(t);
```
All __rvalue does is flag the expression in ( ) as an rvalue. Then the rest of
the semantics go from there. Note that a struct parameter with a move
constructor will always pass by ref regardless, which is what we want here.
Also, move semantics will only work on structs. Not classes, integers, pointers,
arrays, etc. If move semantics are desired for them, they'll need to be wrapped
in a struct, or use a template to wrap it for you.
Consider:
```
this(ref S); // copy constructor
this(@move S); // move constructor
```
I don't know how to make overloading work with this.
More information about the Digitalmars-d
mailing list