www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to realize copyable/postblit class

reply "SimonN" <eiderdaus gmail.com> writes:
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
Jun 12 2015
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
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; } }
Jun 13 2015
parent "SimonN" <eiderdaus gmail.com> writes:
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
Jun 13 2015