DIP 1008 Preliminary Review Round 1

Stanislav Blinov via Digitalmars-d digitalmars-d at puremagic.com
Fri May 19 10:48:55 PDT 2017


On Friday, 19 May 2017 at 17:05:09 UTC, H. S. Teoh wrote:
> On Fri, May 19, 2017 at 05:13:34PM +0100, rikki cattermole via 
> Digitalmars-d wrote: [...]
>> "Code that needs to leak the thrown exception object can clone 
>> the object."
>> 
>> Errors:
>> ```D
>> import std.stdio;
>> void main() {
>> 	auto e = new Exception("foo");
>> 	e = e.dup;
>> 	writeln(e.toString());
>> }
>> ```
>> 
>> Let's just say, I am unaware of a way to duplicate classes. 
>> Assuming I'm messing something, a code example would be very 
>> appreciated in the DIP.
>
> AFAIK, there is no way to clone classes, unless the class 
> writer implemented it explicitly. Only arrays support .dup, no 
> other type does (unless user code explicitly implements it, or 
> its equivalent).
>
>
> T

Well, not that it's a complete implementation or anything, but it 
definitely could be done with a library:

/// Make a shallow clone of a class instance
/// (members that are classes are not cloned)
C clone(C)(C src) if (is(C == class))
{
     // could probably just dynamic cast and copy
     // from most derived...
     assert(typeid(src) == typeid(C));
     // can use any memory allocator here,
     // assuming deallocation is handled correctly
     import core.memory : GC;
     import core.exception : onOutOfMemoryError;
     auto ptr = GC.malloc(__traits(classInstanceSize, C));
     ptr || onOutOfMemoryError;
     scope (failure) GC.free(ptr);

     C dst = cast(C)ptr;

     import std.traits : BaseClassesTuple;
     import std.meta : AliasSeq;
     import core.stdc.string : memcpy;
     foreach(T; AliasSeq!(C, BaseClassesTuple!C)) {
         T bsrc = src;
         T bdst = dst;
         foreach(i, ref _; bsrc.tupleof) {
             alias M = typeof(_);
             memcpy(&bdst.tupleof[i], &bsrc.tupleof[i], M.sizeof);
             static if (__traits(hasMember, M, "__postblit"))
                 bdst.tupleof[i].__postblit;
         }
     }

     return dst;
}

void main() {
     import std.stdio;
     struct Struct {
         int[] data;
         this(this) {
             data = data.dup;
             writeln("Struct is copied");
         }
     }

     class Klass {
         int value;
         Struct s;
         this(int v) {
             value = v;
             s = Struct([1, 2, 3, 4, 5]);
         }
     }

     auto c1 = new Klass(42);
     auto c2 = c1.clone;
     assert(c2);
     assert(c2 !is c1);
     assert(c2.value == 42);
     assert(c2.s.data);
     assert(c2.s.data !is c1.s.data);
     assert(c2.s.data == c1.s.data);
}



More information about the Digitalmars-d mailing list