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