digitalmars.D.learn - Struct copy, how?
- nobody (54/54) Jan 02 2009 (D 1.0)
- BCS (17/30) Jan 02 2009 I think you almost spotted the cause. Bear contains an array (a referenc...
- nobody (8/38) Jan 02 2009 Oh I see. I find it a bit odd that it's copied in this manner, but I bet...
- bearophile (5/15) Jan 03 2009 If you create a generic deep copy I may find it useful.
- nobody (4/20) Jan 03 2009 Heh, unfortunately I wouldn't even know where to begin in order to make
- Daniel Keep (15/37) Jan 04 2009 Off the top of my head, it wouldn't be terribly hard.
- Christopher Wright (8/27) Jan 04 2009 You want ddup to be polymorphic. Let's say you have a class with no
- Daniel Keep (6/35) Jan 04 2009 Obviously, you'd need to have the class support it itself; but the
(D 1.0) After some problems with my program I found where my problems arose. In my mini example: A function that is supposed to create a new bear from 2 exisiting bears ends up altering the original bears. I suspect it has to do with the line ' Bear newBear = bear1;', in that it doesn't copy the contents of the struct. Is there a way to copy a struct without resorting to iterating over all its elements manually? module main; import std.stdio; struct Claw { int n; } struct Bear { Claw[] claw; } struct StoredBears { Bear[] bear; } StoredBears storedBears; Bear mixBears(Bear bear1, Bear bear2) { Bear newBear = bear1; writefln(storedBears.bear[0].claw[0].n); writefln(storedBears.bear[1].claw[0].n); writefln(bear1.claw[0].n); writefln(bear2.claw[0].n); writefln(newBear.claw[0].n); writefln(); newBear.claw[0].n = bear2.claw[0].n; writefln(storedBears.bear[0].claw[0].n); writefln(storedBears.bear[1].claw[0].n); writefln(bear1.claw[0].n); writefln(bear2.claw[0].n); writefln(newBear.claw[0].n); return newBear; } void main() { //create 2 bears and put them in the storedBears struct created above Bear storedBear1; storedBear1.claw.length = 1; storedBear1.claw[0].n = 1; storedBears.bear ~= storedBear1; Bear storedBear2; storedBear2.claw.length = 1; storedBear2.claw[0].n = 2; storedBears.bear ~= storedBear2; //create a new bear from the 2 bears Bear newBear = mixBears(storedBears.bear[0],storedBears.bear[1]); }
Jan 02 2009
Reply to nobody,(D 1.0) After some problems with my program I found where my problems arose. In my mini example: A function that is supposed to create a new bear from 2 exisiting bears ends up altering the original bears. I suspect it has to do with the line ' Bear newBear = bear1;', in that it doesn't copy the contents of the struct. Is there a way to copy a struct without resorting to iterating over all its elements manually?I think you almost spotted the cause. Bear contains an array (a reference type) of Claws. When you copy it you get a new struct with a copy of that array (again a reference). Because that array is a reference type it still referees to that same set of Claws. You can fix this by copying/duping the array Bear newBear = bear1; newBear.claw = bear1.claw.dup; IIRC struct now have an opAssign that can burry this in the struct code rather than the client code. However this still has a few problems: 1, if claw contains a reference type you will now have 2 Claws that refer to the same thing and 2, you need to maintain opAssign to be sure that it copies all members. One way to attack both of these would be to use a template to build a generic deep copy that uses compile time refection to copy all the members, duping arrays of PODS, copying basic types and recursively deep copying reference types and arrays of them.
Jan 02 2009
"BCS" <ao pathlink.com> wrote in message news:78ccfa2d380248cb3b2f9739eb46 news.digitalmars.com...Reply to nobody,Oh I see. I find it a bit odd that it's copied in this manner, but I bet there's good reasons for it. Totally unexpected to me though :)(D 1.0) After some problems with my program I found where my problems arose. In my mini example: A function that is supposed to create a new bear from 2 exisiting bears ends up altering the original bears. I suspect it has to do with the line ' Bear newBear = bear1;', in that it doesn't copy the contents of the struct. Is there a way to copy a struct without resorting to iterating over all its elements manually?I think you almost spotted the cause. Bear contains an array (a reference type) of Claws. When you copy it you get a new struct with a copy of that array (again a reference). Because that array is a reference type it still referees to that same set of Claws. You can fix this by copying/duping the arrayBear newBear = bear1; newBear.claw = bear1.claw.dup; IIRC struct now have an opAssign that can burry this in the struct code rather than the client code.Is opAssign available in D1.0?However this still has a few problems: 1, if claw contains a reference type you will now have 2 Claws that refer to the same thing and 2, you need to maintain opAssign to be sure that it copies all members. One way to attack both of these would be to use a template to build a generic deep copy that uses compile time refection to copy all the members, duping arrays of PODS, copying basic types and recursively deep copying reference types and arrays of them.Guess I'll do that. Thanks for the help!
Jan 02 2009
nobody: BCS:However this still has a few problems: 1, if claw contains a reference type you will now have 2 Claws that refer to the same thing and 2, you need to maintain opAssign to be sure that it copies all members. One way to attack both of these would be to use a template to build a generic deep copy that uses compile time refection to copy all the members, duping arrays of PODS, copying basic types and recursively deep copying reference types and arrays of them.Guess I'll do that. Thanks for the help!If you create a generic deep copy I may find it useful. Bye, bearophile
Jan 03 2009
"bearophile" <bearophileHUGS lycos.com> wrote in message news:gjn7s1$1vk4$1 digitalmars.com...nobody: BCS:Heh, unfortunately I wouldn't even know where to begin in order to make something like that.However this still has a few problems: 1, if claw contains a reference type you will now have 2 Claws that refer to the same thing and 2, you need to maintain opAssign to be sure that it copies all members. One way to attack both of these would be to use a template to build a generic deep copy that uses compile time refection to copy all the members, duping arrays of PODS, copying basic types and recursively deep copying reference types and arrays of them.Guess I'll do that. Thanks for the help!If you create a generic deep copy I may find it useful. Bye, bearophile
Jan 03 2009
nobody wrote:"bearophile" <bearophileHUGS lycos.com> wrote in message news:gjn7s1$1vk4$1 digitalmars.com...Off the top of my head, it wouldn't be terribly hard. What you would need is a global 'ddup' (deep-dup) function. The generic case would look something like: T ddup(T)(ref T value) { T result; foreach( i,f ; value.tupleof ) result.tupleof[i] = ddup(f); return result; } You'd then have to use either specialisation or lots of static if's to account for reference types, allocating new memory as necessary. Can't see any particular reason why you couldn't do it... -- Danielnobody: BCS:Heh, unfortunately I wouldn't even know where to begin in order to make something like that.If you create a generic deep copy I may find it useful. Bye, bearophileHowever this still has a few problems: 1, if claw contains a reference type you will now have 2 Claws that refer to the same thing and 2, you need to maintain opAssign to be sure that it copies all members. One way to attack both of these would be to use a template to build a generic deep copy that uses compile time refection to copy all the members, duping arrays of PODS, copying basic types and recursively deep copying reference types and arrays of them.Guess I'll do that. Thanks for the help!
Jan 04 2009
Daniel Keep wrote:Off the top of my head, it wouldn't be terribly hard. What you would need is a global 'ddup' (deep-dup) function. The generic case would look something like: T ddup(T)(ref T value) { T result; foreach( i,f ; value.tupleof ) result.tupleof[i] = ddup(f); return result; } You'd then have to use either specialisation or lots of static if's to account for reference types, allocating new memory as necessary. Can't see any particular reason why you couldn't do it... -- DanielYou want ddup to be polymorphic. Let's say you have a class with no default constructor, or a class that starts listening on a socket with some default local port -- in the first case, you couldn't ddup it without some ugliness; in the second, you could ddup it, but you'd get an exception because the port's already in use. It would suffice to have an IClonable interface, and to check structs for a ddup property.
Jan 04 2009
Christopher Wright wrote:Daniel Keep wrote:Obviously, you'd need to have the class support it itself; but the original question was in regards to a struct deep copy. :P For reference, I've written a generic serialise/deserialise pair of functions that do, more or less, the same thing, so it can be done. -- DanielOff the top of my head, it wouldn't be terribly hard. What you would need is a global 'ddup' (deep-dup) function. The generic case would look something like: T ddup(T)(ref T value) { T result; foreach( i,f ; value.tupleof ) result.tupleof[i] = ddup(f); return result; } You'd then have to use either specialisation or lots of static if's to account for reference types, allocating new memory as necessary. Can't see any particular reason why you couldn't do it... -- DanielYou want ddup to be polymorphic. Let's say you have a class with no default constructor, or a class that starts listening on a socket with some default local port -- in the first case, you couldn't ddup it without some ugliness; in the second, you could ddup it, but you'd get an exception because the port's already in use. It would suffice to have an IClonable interface, and to check structs for a ddup property.
Jan 04 2009