Thread overview
How to realize copyable/postblit class
Jun 13, 2015
SimonN
Jun 13, 2015
John Colvin
Jun 13, 2015
SimonN
June 13, 2015
Hi,

I have a few classes with need for deeper copying. I don't want a bitwise copy necessarily. Ideally, I'd implement this(this).

I've thought about changing them to struct. However, the type feels much more like a D class than a D struct. It's often passed by reference, and it's not plain old data. Changing it to struct for the sole benefit of "this(this)" seems to be a bad tradeoff.

(Use case: Backing up game states in a for savestating/networking.)

I've resorted to a C++-style copy constructor:

this(T rhs) {
    myvalue = rhs.myvalue;
    myarray = rhs.myarray.dup;
    // ...
}

Downside: Boilerplate, each member appears once in the declarations, a second time in the copy constructor.

Alternative approaches seem to implement T T.dup() or T T.clone(). Apparently, one has to pick one of these equally good approaches, and stick with it throughout a codebase. It seems good to implement it only for the classes that need it, to minimize boilerplate.

Is that the state of the art?

-- Simon
June 13, 2015
On Saturday, 13 June 2015 at 05:20:42 UTC, SimonN wrote:
> Hi,
>
> I have a few classes with need for deeper copying. I don't want a bitwise copy necessarily. Ideally, I'd implement this(this).
>
> I've thought about changing them to struct. However, the type feels much more like a D class than a D struct. It's often passed by reference, and it's not plain old data. Changing it to struct for the sole benefit of "this(this)" seems to be a bad tradeoff.
>
> (Use case: Backing up game states in a for savestating/networking.)
>
> I've resorted to a C++-style copy constructor:
>
> this(T rhs) {
>     myvalue = rhs.myvalue;
>     myarray = rhs.myarray.dup;
>     // ...
> }
>
> Downside: Boilerplate, each member appears once in the declarations, a second time in the copy constructor.
>
> Alternative approaches seem to implement T T.dup() or T T.clone(). Apparently, one has to pick one of these equally good approaches, and stick with it throughout a codebase. It seems good to implement it only for the classes that need it, to minimize boilerplate.
>
> Is that the state of the art?
>
> -- Simon

perhaps:

class A
{
    struct S
    {
        //class contents
        this(this){ /*any extra post-copy fixeup you need*}
    }
    S s;
    //to avoid having to type A.s.myMember
    alias s this; //or could use std.typecons.Proxy
    this(A rhs)
    {
        s = rhs.s;
    }
}
June 13, 2015
On Saturday, 13 June 2015 at 08:52:59 UTC, John Colvin wrote:
> perhaps:
>
> class A
> {
>     struct S
>     {
>         // ...
>     }
>     S s;
>     alias s this;
>     this(A rhs)
>     {
>         s = rhs.s;
>     }
> }

I'm using this now, and it doesn't feel like a workaround too much.

For something with 5 value fields, it's already shorter than the original solution.

Thanks! :-)

-- Simon