August 20, 2005 Re: How to copy an object? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Burton Radons | "Burton Radons" <burton-radons@smocky.com> wrote in message news:de838k$1ouu$1@digitaldaemon.com... > Haha, why'd I put that in a template? It just hides the cast. That should be: > > private extern (C) Object _d_newclass (ClassInfo info); > > Object shallow_copy (Object value) > { > if (value is null) > return null; > > void *copy = _d_newclass (value.classinfo); > size_t size = value.classinfo.init.length; > > copy [8 .. size] = (cast (void *) value) [8 .. size]; > return cast (Object) copy; > } > > Better to start at that offset to avoid copying the synchronisation handle over, plus it's pointless work. It's too bad it depends on a compiler-specific function (_d_newclass) and doesn't allow classes to say they don't want to be shallow_copied because they have a custom allocator or constructor behavior. Something slightly less risky would be something like /** Clobbers an object with the contents of another object of the same * class. Clobbering an arbitrary object is very risky so only use the * function inside of a dup() method in a class after creating the * target duplicate. For example, * class Foo { * int test; * int some_other_state; * this(int t) { test = t; } * Foo dup() { * Foo res = new Foo(test); * clobber(res, this); * return res; * } * } * ... * Foo x = new Foo(10); * ... * Foo y = x.dup; */ void clobber(Object dest, Object source) { ClassInfo ci = source.classinfo; if (ci !is dest.classinfo) throw new Exception("Cannot clobber subclasses or superclasses"); void* s = source; void* d = dest; size_t start = Object.classinfo.init.length; d[start .. ci.init.length] = s[start .. ci.init.length]; } |
August 21, 2005 Re: How to copy an object? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ben Hinkle | On Sat, 20 Aug 2005 19:21:17 -0400, "Ben Hinkle" <ben.hinkle@gmail.com> wrote:
>
>"Burton Radons" <burton-radons@smocky.com> wrote in message news:de838k$1ouu$1@digitaldaemon.com...
>> Haha, why'd I put that in a template? It just hides the cast. That should be:
>>
>> private extern (C) Object _d_newclass (ClassInfo info);
>>
>> Object shallow_copy (Object value)
>> {
>> if (value is null)
>> return null;
>>
>> void *copy = _d_newclass (value.classinfo);
>> size_t size = value.classinfo.init.length;
>>
>> copy [8 .. size] = (cast (void *) value) [8 .. size];
>> return cast (Object) copy;
>> }
>>
>> Better to start at that offset to avoid copying the synchronisation handle over, plus it's pointless work.
>
>It's too bad it depends on a compiler-specific function (_d_newclass) and doesn't allow classes to say they don't want to be shallow_copied because they have a custom allocator or constructor behavior. Something slightly less risky would be something like
>
>/** Clobbers an object with the contents of another object of the same
> * class. Clobbering an arbitrary object is very risky so only use the
> * function inside of a dup() method in a class after creating the
> * target duplicate. For example,
> * class Foo {
> * int test;
> * int some_other_state;
> * this(int t) { test = t; }
> * Foo dup() {
> * Foo res = new Foo(test);
> * clobber(res, this);
> * return res;
> * }
> * }
> * ...
> * Foo x = new Foo(10);
> * ...
> * Foo y = x.dup;
> */
>void clobber(Object dest, Object source) {
> ClassInfo ci = source.classinfo;
> if (ci !is dest.classinfo)
> throw new Exception("Cannot clobber subclasses or superclasses");
> void* s = source;
> void* d = dest;
> size_t start = Object.classinfo.init.length;
> d[start .. ci.init.length] = s[start .. ci.init.length];
>}
Doesn't bar.dup() fail for a subclass Bar of Foo? Unless I reimplement
it, of course.
-Chuck
|
August 21, 2005 Re: How to copy an object? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Burton Radons | On Sat, 20 Aug 2005 13:19:41 -0700, Burton Radons <burton-radons@smocky.com> wrote:
>Haha, why'd I put that in a template? It just hides the cast. That should be:
>
> private extern (C) Object _d_newclass (ClassInfo info);
>
> Object shallow_copy (Object value)
> {
> if (value is null)
> return null;
>
> void *copy = _d_newclass (value.classinfo);
> size_t size = value.classinfo.init.length;
>
> copy [8 .. size] = (cast (void *) value) [8 .. size];
> return cast (Object) copy;
> }
>
>Better to start at that offset to avoid copying the synchronisation handle over, plus it's pointless work.
Thanks, Burton. That's pretty neat. I had figured out the "value.classinfo.init.length", but not the _d_newclass.
As Ben points out, it won't work with custom allocators, but since I'm using any in my own classes, that's fine.
-Chuck
|
August 21, 2005 Re: How to copy an object? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chuck Esterbrook | "Chuck Esterbrook" <Chuck.Esterbrook@gmail.antispam.com> wrote in message news:3eifg1h5rbi03ql7etpur7i8645kumptet@4ax.com... > On Sat, 20 Aug 2005 19:21:17 -0400, "Ben Hinkle" <ben.hinkle@gmail.com> wrote: > >> >>"Burton Radons" <burton-radons@smocky.com> wrote in message news:de838k$1ouu$1@digitaldaemon.com... >>> Haha, why'd I put that in a template? It just hides the cast. That should be: >>> >>> private extern (C) Object _d_newclass (ClassInfo info); >>> >>> Object shallow_copy (Object value) >>> { >>> if (value is null) >>> return null; >>> >>> void *copy = _d_newclass (value.classinfo); >>> size_t size = value.classinfo.init.length; >>> >>> copy [8 .. size] = (cast (void *) value) [8 .. size]; >>> return cast (Object) copy; >>> } >>> >>> Better to start at that offset to avoid copying the synchronisation >>> handle >>> over, plus it's pointless work. >> >>It's too bad it depends on a compiler-specific function (_d_newclass) and doesn't allow classes to say they don't want to be shallow_copied because they have a custom allocator or constructor behavior. Something slightly less risky would be something like >> >>/** Clobbers an object with the contents of another object of the same >> * class. Clobbering an arbitrary object is very risky so only use the >> * function inside of a dup() method in a class after creating the >> * target duplicate. For example, >> * class Foo { >> * int test; >> * int some_other_state; >> * this(int t) { test = t; } >> * Foo dup() { >> * Foo res = new Foo(test); >> * clobber(res, this); >> * return res; >> * } >> * } >> * ... >> * Foo x = new Foo(10); >> * ... >> * Foo y = x.dup; >> */ >>void clobber(Object dest, Object source) { >> ClassInfo ci = source.classinfo; >> if (ci !is dest.classinfo) >> throw new Exception("Cannot clobber subclasses or superclasses"); >> void* s = source; >> void* d = dest; >> size_t start = Object.classinfo.init.length; >> d[start .. ci.init.length] = s[start .. ci.init.length]; >>} > > > Doesn't bar.dup() fail for a subclass Bar of Foo? Unless I reimplement > it, of course. > > -Chuck Yeah. That's on purpose - I'd like subclasses to always say how they dup just like they say how they are constructed. One can call _d_newclass and clobber that if you want to let subclasses inherit dup "silently". For classes that can be subclassed I'd probably go with using clobber in a copy constructor instead of inside dup, actually: class Foo { this(Foo obj) { clobber(this,obj); } ... } Then there's no confusion about dup having to be overriden by the subclass. |
Copyright © 1999-2021 by the D Language Foundation