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);
}

Reply via email to