Discussion Thread: DIP 1040--Copying, Moving, and Forwarding--Community Review Round 1
Q. Schroll
qs.il.paperinik at gmail.com
Wed Mar 17 17:14:04 UTC 2021
On Thursday, 11 March 2021 at 03:33:31 UTC, Walter Bright wrote:
> On 3/10/2021 5:27 PM, tsbockman wrote:
>> On Thursday, 11 March 2021 at 00:31:01 UTC, deadalnix wrote:
>>> On Wednesday, 10 March 2021 at 22:51:58 UTC, tsbockman wrote:
>>>> Am I the only one who thinks that it would be better to have
>>>> syntax that accurately reflects the semantics, instead of
>>>> just documenting "this syntax is a lie"?
>>>
>>> No, I think there is a problem with using opAssign here,
>>> because "this" will refers to something that is possibly
>>> uninitialized, and the old value may not be consumed fully.
>>>
>>> Due to problem #1, this kinda need to be a constructor rather
>>> than an opAssign.
>
> opAssign is only for assigning to initialized objects.
> Constructors are for uninitialized objects.
>
>
>> Yeah, studying the DIP I can't figure out what problem the
>> move `opAssign` is supposed to solve that the constructor
>> doesn't:
>> https://forum.dlang.org/post/kzgybicwqwlfyiiefucc@forum.dlang.org
>
> The thing about "destroy after move" is to deal with the case
> of both the source and the destination referring to the same
> object. The concern is that destroying the destination's
> original contents first will destroy them for the source before
> it gets moved in.
>
> It's the same problem "swap" has. It's also necessary semantics
> for a reference counted object.
It might be a stupid question, but why have move assignment in
the first place? In C++, there's the copy-and-swap idiom[1].
Maybe it's obvious why it does not apply in D, but if using a
swap function makes implementing a copy assignment and move
assignment trivial, why not requiring opSwap instead of opAssign
for an elaborate move object?
Basically, opSwap takes a typeof(this) lvalue (by reference),
well, swaps contents with `this`. Usually, this means swapping
all member variables (can be auto-generated easily). Then,
ref typeof(this) opAssign(typeof(this) rhs)
{
this.opSwap(rhs);
return this;
}
does the deed. Note that the call to opAssign is to be treated
like any old member function call. If the argument is an rvalue
(or by the DIP the last use of an lvalue), the move constructor
is used to initialize the parameter. Otherwise the copy
constructor is used to initialize the parameter.
This is not a "let's do it like C++ guides" but rather "let's not
repeat the mistakes C++ made". Because in C++, if one don't know
copy-and-swap, one's copy/move assignment operator is probably
worse than the copy-and-swap one.
Note that in C++, too, copy-and-swap only applies to elaborate
move objects.
[1]
https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom
More information about the Digitalmars-d
mailing list