Discussion Thread: DIP 1040--Copying, Moving, and Forwarding--Community Review Round 1

tsbockman thomas.bockman at gmail.com
Fri Mar 12 01:40:22 UTC 2021


On Thursday, 11 March 2021 at 21:45:49 UTC, tsbockman wrote:
> On Thursday, 11 March 2021 at 08:36:18 UTC, Walter Bright wrote:
>> On 3/10/2021 8:17 PM, tsbockman wrote:
>>> Wouldn't it make more sense to just skip the move operation 
>>> entirely when the source and destination are the same? Or are 
>>> there circumstances in which that cannot be determined, even 
>>> at runtime?
>>
>> The idea is that the move assignment operation takes care of 
>> this, and makes it "as if" the move was done, then the 
>> destruction.
>
> My concern is how to make code like this work correctly:
> ...
> // Maybe this is your proposed lowering for the `a = b;` line 
> in main, above?
> {
>     S oldDest = a; // You all say no copy constructor call is 
> necessary here, but...
>     a.opAssign(b); // (Body is the same as that of the move 
> constructor.)
>     // ...the implicit destroy(oldDest); at scope exit crashes 
> if oldDest was only blit.
> }
>
> You can put the lowering logic inside of the move opAssign 
> instead, but it doesn't change the fundamental problem. If no 
> actual general-purpose lowering is possible that accurately 
> reflects the intended semantics of, "After the move is 
> complete, the destructor is called on the original contents of 
> the constructed object," then the DIP's description of the 
> semantics is simply incorrect and should be replaced with 
> something more rigorous.

I think I finally figure out how to make some sense out of the 
DIP's description. However, the lowering cannot be expressed 
clearly with the DIP's syntax, so I will use an alternative 
notation:

void moveConstruct(ref S source) nothrow @nogc {
     if(source.isUnique) {
         ptr = &internal;
         internal = source.internal;
     } else
         ptr = source.ptr;
}
void moveAssign(ref S source) @trusted nothrow @nogc {
     S oldDest = void;
     oldDest.moveConstruct(this); // Move the old value to a 
temporary.
     moveConstruct(source);
     // Implicitly destroy the old value.
}

Is this correct? If so, the DIP really needs to explain it more 
clearly - especially if the user is expected to implement some 
equivalent in the custom move operator himself, rather than the 
compiler doing it for him.


More information about the Digitalmars-d mailing list