Generated opAssign in the presence of a copy constructor

Manu turkeyman at gmail.com
Thu Jul 26 16:05:59 UTC 2018


On Thu., 26 Jul. 2018, 2:45 am RazvanN via Digitalmars-d, <
digitalmars-d at puremagic.com> wrote:

> Hello everyone!
>
> As you probably know, I am working on the copy constructor DIP
> and implementation. So far, I managed to implement 95% of the
> copy constructor logic (as stated in the DIP). The point that is
> a bit of a headache is how/when should opAssign be generated when
> a copy constructor is defined. Now here is what I have (big
> thanks to Andrei for all the ideas, suggestions and brainstorms):
>
> -> mutability of struct fields:
>
> If the struct contains any const/immutable fields, it is
> impossible to use the copy constructor for opAssign, because the
> copy constructor might initialize them. Even if the copy
> constructor doesn't touch the const/immutable fields the compiler
> has to analyze the function body to know that, which is
> problematic in situations when the body is missing. => opAssign
> will be generated when the struct contains only assignable
> (mutable) fields.
>
> -> qualifiers:
>
> The copy constructor signature is : `@implicit this(ref $q1 S
> rhs) $q2`, where q1 and q2 represent the qualifiers that can be
> applied to the function and the parameter (const, immutable,
> shared, etc.). The problem that arises is: depending on the
> values of $q1 and $q2 what should the signature of opAssign be?
>
> A solution might be to generate for every copy constructor
> present its counterpart opAssign: `void opAssign(ref $q1 S rhs)
> $q2`. However, when is a const/immutable opAssign needed? There
> might be obscure cases when that is useful, but those are niche
> situations where the user must step it and clarify what the
> desired outcome is and define its own opAssign. For the sake of
> simplicity, opAssign will be generated solely for copy
> constructors that have a missing $q2 = ``.
>
> -> semantics in the presence of a destructor:
>
> If the struct that has a copy constructor does not define a
> destructor, it is easy to create the body of the above-mentioned
> opAssign: the copy constructor is called and that's that:
>
> void opAssign(ref $q1 S rhs)    // version 1
> {
>      S tmp = rhs;        // copy constructor is called
>      memcpy(this, tmp);  // blit it into this
> }


Why the memcpy?
This looks inefficient.

Is it in case the constructor throws?
Have a 'nothrow' case where it constructs directly to this?

Things get interesting when a destructor is defined, because now
> we also have to call it on the destination:
>
> void opAssign(ref $q1 S rhs)   // version 2
> {
>     this.__dtor;           // ensure the dtor is called
>     memcpy(this, S.init)   // bring the object in the initial state
>     this.copyCtor(rhs);    // call constructor on object in .init
> state
> }
>
> The problem with the above solution is that it does not take into
> account the fact
> that the copyCtor may throw and if it does, then the object will
> be in a partially initialized state. In order to overcome this,
> two temporaries are used:
>
> void opAssign(ref $q1 S rhs)    // version 3
> {
>      S tmp1 = rhs;                // call copy constructor
>      void[S.sizeof] tmp2 = void;
>
>      // swapbits(tmp1, this);
>      memcpy(tmp2, this);
>      memcpy(this, tmp1);
>      memcpy(tmp1, tmp2);
>
>      tmp1.__dtor();
> }
>
> In this version, if the copy constructor throws the object will
> still be in a valid state.
>
> -> attribute inference for the generated opAssign:
>
> For version 1: opAssign attributes are inferred based on the copy
> constructor attrbiutes.
> For version 2: opAssign attributes are inferred based on copy
> constructor and destructor attributes
> For version 3: the declaration of the void array can be put
> inside a trusted block and then attributes are inferred based on
> copy constructor and destructor attributes
>
> If the copy constructor is marked `nothrow` and the struct
> defines a destructor, then version 2 is used, otherwise version 3.
>
> What are your thoughts on this?
>
> RazvanN


This all looks about right to me!
I doubt there are any alternative options.

>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20180726/2a27684c/attachment.html>


More information about the Digitalmars-d mailing list