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