digitalmars.D.learn - How to copy an object?
- Chuck Esterbrook (14/14) Aug 19 2005 I want a shallow copy of an object. Something like:
- Manfred Nowak (5/6) Aug 19 2005 [...]
- Chuck Esterbrook (25/31) Aug 20 2005 I assume you're referring to: "Sometimes, one does need to create a
- Ben Hinkle (6/41) Aug 20 2005 Nope. If a class authors wants a class to be copyable they need to write...
- Chuck Esterbrook (11/18) Aug 20 2005 [snip]
- Jarrett Billingsley (3/5) Aug 20 2005 It's typename.sizeof in D. Like int.sizeof or MyClass.sizeof.
- Burton Radons (3/11) Aug 20 2005 sizeof returns the size of the value on the stack, so a class's sizeof
- Chris Sauls (3/18) Aug 20 2005 Would .classinfo.init.size work?
- Burton Radons (15/32) Aug 20 2005 extern (C) Object _d_newclass (ClassInfo info);
- Burton Radons (14/14) Aug 20 2005 Haha, why'd I put that in a template? It just hides the cast. That
- Ben Hinkle (34/48) Aug 20 2005 It's too bad it depends on a compiler-specific function (_d_newclass) an...
- Chuck Esterbrook (5/58) Aug 20 2005 Doesn't bar.dup() fail for a subclass Bar of Foo? Unless I reimplement
- Ben Hinkle (14/76) Aug 20 2005 Yeah. That's on purpose - I'd like subclasses to always say how they dup...
- Chuck Esterbrook (7/21) Aug 20 2005 Thanks, Burton. That's pretty neat. I had figured out the
I want a shallow copy of an object. Something like: where I could assert afterwards that: - obj !is someOtherObj - they have the same class - their data members are identical have to wrap it with a public method). In Python, this is done with the copy module. Is there something analagous in D? (I searched for "copy" and "clone" in various places like this newsgroup, the Phobos docs and Wiki4D, but didn't catch anything.) Thanks, -Chuck
Aug 19 2005
Chuck Esterbrook <Chuck.Esterbrook gmail.antispam.com> wrote:I want a shallow copy of an object.[...] Please read the FAQ: Why is overload the assignment operator not supported? -manfred
Aug 19 2005
On Sat, 20 Aug 2005 05:26:49 +0000 (UTC), Manfred Nowak <svv1999 hotmail.com> wrote:Chuck Esterbrook <Chuck.Esterbrook gmail.antispam.com> wrote:I assume you're referring to: "Sometimes, one does need to create a copy of a class object, and for that one can still write a copy constructor in D" ...as I'm not wanting to redefine =. Let me clarify my question: Is there a general purpose function that is written, or could be written, to take any obj ref and return a copy of it? Something like: Object copy(Object obj) { Object newObj; <insert magic here>; return newObj; } Maybe it would even be something like: Object copy(Object obj) { if (obj is null) return null; int* newObj = cast(int*)malloc(SIZEOF?(obj)); memcpy(newObj, (int*)obj, SIZEOF?(obj)); return cast(Object)newObj; } Or maybe those should be "void*" instead of "int*" above. Also, I don't know how to get the size of any arbitrary object. -ChuckI want a shallow copy of an object.[...] Please read the FAQ: Why is overload the assignment operator not supported? -manfred
Aug 20 2005
"Chuck Esterbrook" <Chuck.Esterbrook gmail.antispam.com> wrote in message news:ji7eg1h3sagap5atgtmufu4uinc6q1kll2 4ax.com...On Sat, 20 Aug 2005 05:26:49 +0000 (UTC), Manfred Nowak <svv1999 hotmail.com> wrote:Nope. If a class authors wants a class to be copyable they need to write either a dup() property or a copy constructor. Technically they can write whatever function they want but dup() is the standard name for the "duplicate" method. What are you trying to do?Chuck Esterbrook <Chuck.Esterbrook gmail.antispam.com> wrote:I assume you're referring to: "Sometimes, one does need to create a copy of a class object, and for that one can still write a copy constructor in D" ...as I'm not wanting to redefine =. Let me clarify my question: Is there a general purpose function that is written, or could be written, to take any obj ref and return a copy of it?I want a shallow copy of an object.[...] Please read the FAQ: Why is overload the assignment operator not supported? -manfredSomething like: Object copy(Object obj) { Object newObj; <insert magic here>; return newObj; } Maybe it would even be something like: Object copy(Object obj) { if (obj is null) return null; int* newObj = cast(int*)malloc(SIZEOF?(obj)); memcpy(newObj, (int*)obj, SIZEOF?(obj)); return cast(Object)newObj; } Or maybe those should be "void*" instead of "int*" above. Also, I don't know how to get the size of any arbitrary object. -Chuck
Aug 20 2005
On Sat, 20 Aug 2005 08:46:59 -0400, "Ben Hinkle" <ben.hinkle gmail.com> wrote:"Chuck Esterbrook" <Chuck.Esterbrook gmail.antispam.com> wrote in message[snip]It would be nice to have this feature to reduce maintenance so that if I add a member var "int _foo;" I don't get burned by forgetting to update dup(). Also, I'm exploring the language and I'm used to having a "shallow one of those things I happen to look for. Thanks for the reply, -ChuckIs there a general purpose function that is written, or could be written, to take any obj ref and return a copy of it?Nope. If a class authors wants a class to be copyable they need to write either a dup() property or a copy constructor. Technically they can write whatever function they want but dup() is the standard name for the "duplicate" method. What are you trying to do?
Aug 20 2005
"Chuck Esterbrook" <Chuck.Esterbrook gmail.antispam.com> wrote in message news:ji7eg1h3sagap5atgtmufu4uinc6q1kll2 4ax.com...Or maybe those should be "void*" instead of "int*" above. Also, I don't know how to get the size of any arbitrary object.It's typename.sizeof in D. Like int.sizeof or MyClass.sizeof.
Aug 20 2005
Jarrett Billingsley wrote:"Chuck Esterbrook" <Chuck.Esterbrook gmail.antispam.com> wrote in message news:ji7eg1h3sagap5atgtmufu4uinc6q1kll2 4ax.com...sizeof returns the size of the value on the stack, so a class's sizeof is always 4.Or maybe those should be "void*" instead of "int*" above. Also, I don't know how to get the size of any arbitrary object.It's typename.sizeof in D. Like int.sizeof or MyClass.sizeof.
Aug 20 2005
Burton Radons wrote:Jarrett Billingsley wrote:Would .classinfo.init.size work? -- Chris Sauls"Chuck Esterbrook" <Chuck.Esterbrook gmail.antispam.com> wrote in message news:ji7eg1h3sagap5atgtmufu4uinc6q1kll2 4ax.com...sizeof returns the size of the value on the stack, so a class's sizeof is always 4.Or maybe those should be "void*" instead of "int*" above. Also, I don't know how to get the size of any arbitrary object.It's typename.sizeof in D. Like int.sizeof or MyClass.sizeof.
Aug 20 2005
Chuck Esterbrook wrote:I want a shallow copy of an object. Something like: where I could assert afterwards that: - obj !is someOtherObj - they have the same class - their data members are identical have to wrap it with a public method). In Python, this is done with the copy module. Is there something analagous in D? (I searched for "copy" and "clone" in various places like this newsgroup, the Phobos docs and Wiki4D, but didn't catch anything.)extern (C) Object _d_newclass (ClassInfo info); template shallow_copy (T : Object) { T shallow_copy (T value) { if (value is null) return null; void *copy = _d_newclass (value.classinfo); size_t size = value.classinfo.init.length; copy [0 .. size] = (cast (void *) value) [0 .. size]; return cast (T) copy; } } :Q
Aug 20 2005
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.
Aug 20 2005
"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]; }
Aug 20 2005
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...Doesn't bar.dup() fail for a subclass Bar of Foo? Unless I reimplement it, of course. -ChuckHaha, 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]; }
Aug 20 2005
"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: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."Burton Radons" <burton-radons smocky.com> wrote in message news:de838k$1ouu$1 digitaldaemon.com...Doesn't bar.dup() fail for a subclass Bar of Foo? Unless I reimplement it, of course. -ChuckHaha, 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]; }
Aug 20 2005
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
Aug 20 2005