digitalmars.D - potential behavior of nested structs
- Era Scarecrow (87/87) Feb 03 2013 Branched off since this seems appropriate.
- Maxim Fomin (13/18) Feb 03 2013 Strictly speaking they are not illegal, they just do not have
- Era Scarecrow (11/25) Feb 04 2013 I'm aware of that. With nested structs we know they will be part
- Dicebot (3/3) Feb 04 2013 Nested types with hidden context pointers is one of D features I
- Era Scarecrow (7/10) Feb 04 2013 They already exist for classes though; Or so I understand.
- Zach the Mystic (2/12) Feb 04 2013 Hey I've been working on this. Thanks for holding the fort down.
- Era Scarecrow (15/24) Feb 04 2013 After reading your post (Atoms, protons, neurons) I can see
- Timon Gehr (2/5) Feb 04 2013 Use 'static'. Anyway, there is nothing wrong with those.
- Dicebot (2/8) Feb 05 2013 You are my savior. Didn't know this was defined. Will switch.
Branched off since this seems appropriate. Currently nested structs are illegal, since having them on the stack passing them with a context pointer would result in illegal code or undefined behavior. struct Outer { struct Inner { string innerString; string getOuterString() { return outerString; } } string outerString; Inner innerInstance; } auto func(Outer x) { return x.innerInstance; } //inner needs outer instance, is not immediately usable. Outer.Inner inner; Outer outer; //points to temporary 'x' from func, likely garbage inner = func(outer); If Outer had been a class, then being on the heap the problem goes away, plus the class is always by reference. Considering behavior for making nested structs legal, it would require a few extra rules to ensure it would be safe to use. 1) It cannot return a nested struct outside of it's level of control where it can ensure it exists. Alternatively returning a nested struct (outside of it's own implementation) could be downright illegal, but that seems too limiting. //error, x is a temporary Inner func(Outer x){return x.innerInstance; } //Inner still valid after call. Inner func(ref Outer x){return x.innerInstance; } 2) Nested structs need context pointers, however with being able to swap structs at a whim having an address as part of the struct's contents is impractical. In this case the structs being passed has to silently pass in the function call the related pointers. If it's nested multiple levels, each level would have to be referenced. If you don't/can't return it outside a function receiving it (or it's parent), then it's as safe as ref is. struct Outer { struct Inner {} void func(Inner x) {} //translates to void func(ref Outer this, ref Outer xPtr, Inner x) {} } 3) If the nested struct has no data then it's more a name-space for behavior (and an alias for the outer/parent struct). If the nested struct does not actually use it's parents data in any methods, then it can in turn be copied/returned without any extra context pointers. 4) Nested structs's may rely on their parent's data, but the parents don't have to rely on the nested struct's data (If they do, then opAssign would be needed, or postblit to handle the changes). An example of this is potentially in a DB environment where a struct holding a text query can be replaced by a compiled version of that query, the parent doesn't need to know. struct Dog { string dogName; struct Tail { string colorOf = "Black"; //just data. string name() { return dogName; } } Tail tail; void func(ref Dog rhs) { //tail2 retains context pointer to rhs. Tail tail2 = rhs.tail; writeln(tail.name()); //Scruffy writeln(tail2.name()); //Spike } //ref, otherwise illegal to return Tail doesSomething(ref Outer rhs) { return rhs.tail; } } Dog dog1 = Dog("Scruffy"); Dog dog2 = Dog("Spike"); dog2.tail.colorOf = "White"; dog1.func(dog2); //context pointer to dog2 thrown away after copy, //unless opAssign declared and does something. //so dog1's tail belongs to dog1, not dog2 dog1.tail = dog2.tail; assert(dog1.dogName == "Scruffy"); //untouched assert(dog1.tail.name == "Scruffy"); //dog1 owns tail, not dog2 assert(dog1.tail.colorOf == "White"); //data copied for tail. Thoughts and ideas?
Feb 03 2013
On Monday, 4 February 2013 at 00:26:10 UTC, Era Scarecrow wrote:Branched off since this seems appropriate. Currently nested structs are illegal, since having them on the stack passing them with a context pointer would result in illegal code or undefined behavior.Strictly speaking they are not illegal, they just do not have context pointer which points to enclosing struct. Thus, even if you manage to return outer struct data from inner, this would not work if nested struct is created alone, without outer struct.Thoughts and ideas?I do not think there are problems with how nested structs with context pointer should be defined. I consider implementation to be a serious problem since we often have <100 messages in forum and no practice steps. What I expect to be a problem is storing pointer to outer struct in nested struct. The problem is that most structs are stack allocated and stack pointer can be invalidated. Example http://d.puremagic.com/issues/show_bug.cgi?id=9352
Feb 03 2013
On Monday, 4 February 2013 at 07:15:47 UTC, Maxim Fomin wrote:Strictly speaking they are not illegal, they just do not have context pointer which points to enclosing struct. Thus, even if you manage to return outer struct data from inner, this would not work if nested struct is created alone, without outer struct.I'm aware of that. With nested structs we know they will be part of a larger structure so making & using them outside of their parent struct just doesn't work; At best you can move them as storage but couldn't instantiate them yourself.Yes I know, this is why returning a struct beyond it's level or where it may be invalidated wouldn't be allowed, which combats this (or even removes it altogether). But as much as I think on the matter of nested structs, I keep coming back to that they are an implementation detail of the parent structs and not really intended to leave them.Thoughts and ideas?I do not think there are problems with how nested structs with context pointer should be defined. I consider implementation to be a serious problem since we often have <100 messages in forum and no practice steps. What I expect to be a problem is storing pointer to outer struct in nested struct. The problem is that most structs are stack allocated and stack pointer can be invalidated. Example http://d.puremagic.com/issues/show_bug.cgi?id=9352
Feb 04 2013
Nested types with hidden context pointers is one of D features I do not like at all. Please leave me at least my structs. :(
Feb 04 2013
On Monday, 4 February 2013 at 14:37:29 UTC, Dicebot wrote:Nested types with hidden context pointers is one of D features I do not like at all. Please leave me at least my structs. :(They already exist for classes though; Or so I understand. They would be rare; But I've had the need for them with non-classes (say a sorting algorithm that's also a range) it's an annoyance to manually do it using pointers and then having to update said pointers. It can be done... It's just ugly and doesn't feel like I should have to.
Feb 04 2013
On Monday, 4 February 2013 at 22:17:04 UTC, Era Scarecrow wrote:On Monday, 4 February 2013 at 14:37:29 UTC, Dicebot wrote:Hey I've been working on this. Thanks for holding the fort down.Nested types with hidden context pointers is one of D features I do not like at all. Please leave me at least my structs. :(They already exist for classes though; Or so I understand. They would be rare; But I've had the need for them with non-classes (say a sorting algorithm that's also a range) it's an annoyance to manually do it using pointers and then having to update said pointers. It can be done... It's just ugly and doesn't feel like I should have to.
Feb 04 2013
On Monday, 4 February 2013 at 22:42:52 UTC, Zach the Mystic wrote:On Monday, 4 February 2013 at 22:17:04 UTC, Era Scarecrow wrote:After reading your post (Atoms, protons, neurons) I can see we're thinking a lot on the same lines; Although yours doesn't get into limitations of when not to return a nested struct, But if the implementation never leaves the outer/parent struct then it doesn't matter. This would be something for someone to try incorporating into a test version of the front end and just see how it works. Kinda like the property problem, some things you just gotta try yourself with an implementation before you know if it's a good design. Thankfully if it is allowed it couldn't possibly break code (as they aren't allowed right now). But that's up to Andrei and Walter to decide if it's allowed, we don't want to have create/break specs and split the community.They already exist for classes though; Or so I understand. They would be rare; But I've had the need for them with non-classes (say a sorting algorithm that's also a range) it's an annoyance to manually do it using pointers and then having to update said pointers. It can be done... It's just ugly and doesn't feel like I should have to.Hey I've been working on this. Thanks for holding the fort down.
Feb 04 2013
On 02/04/2013 03:37 PM, Dicebot wrote:Nested types with hidden context pointers is one of D features I do not like at all. Please leave me at least my structs. :(Use 'static'. Anyway, there is nothing wrong with those.
Feb 04 2013
On Tuesday, 5 February 2013 at 00:19:19 UTC, Timon Gehr wrote:On 02/04/2013 03:37 PM, Dicebot wrote:You are my savior. Didn't know this was defined. Will switch.Nested types with hidden context pointers is one of D features I do not like at all. Please leave me at least my structs. :(Use 'static'. Anyway, there is nothing wrong with those.
Feb 05 2013