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

tsbockman thomas.bockman at gmail.com
Fri Mar 12 23:47:20 UTC 2021


On Friday, 5 March 2021 at 12:19:54 UTC, Mike Parker wrote:
> This is the discussion thread for the first round of Community 
> Review of DIP 1040, "Copying, Moving, and Forwarding":

The default field-wise move operators seem to have been specified 
with no concern for maintaining consistency between the semantics 
of custom operators and default operators:

 From the DIP:
> If a Move Assignment Operator is not defined for a struct that
> has a Move Constructor, a default Move Assignment Operator is
> defined and implemented as a move for each of its fields, in
> lexical order.

If a custom move constructor is present for a good reason, that 
means that simply moving the fields one-by-one is *not* the 
desired move behavior.

Instead, the default move assignment operator should call the 
struct's move constructor and destructor in one of the two valid 
patterns that I found earlier in this discussion (link to a full 
working example):
     
https://gist.github.com/run-dlang/b789714c01905f091a44ee2666276433

// Using an alternative syntax so that this can be tested today:
void moveAssign(ref S source) @trusted nothrow @nogc {
     static if(useDIPLowering) {
         // destroy after (the DIP's proposal):
         S newVal = void;
         newVal.moveConstruct(source);
         S oldVal = void;
         oldVal.moveConstruct(this);
         moveConstruct(newVal);
         // Implicitly destruct(oldVal).
     } else {
         // conditionally move and destroy before (my proposal):
         if(&source !is &this) {
             destruct(this);
             moveConstruct(source);
         }
     }
}

Also from the DIP:
> If a Move Constructor is not defined for a struct that has a 
> Move
> Assignment Operator, a default Move Constructor is defined and
> implemented as a move for each of its fields, in lexical order.

Again, the presence of a custom move assignment operator 
indicates that non-default move behavior is desired. 
Auto-generating a default move constructor is a missed 
opportunity to point out a semantic inconsistency in the user's 
work.

Defining a custom move assignment operator without a custom move 
constructor to go with it should be a compile-time error, because 
there is no automated way to extract a valid move constructor 
from a custom move assignment operator.

In the unlikely case that the omission of the custom move 
constructor is intentional, people can manually defining a 
field-wise move constructor (which is not difficult), or annotate 
that constructor with @disable.


More information about the Digitalmars-d mailing list