digitalmars.D.learn - Why no acess to other structs in classes?
- Karen Lanrap (17/17) Nov 05 2006 class C
- John Demme (21/38) Nov 05 2006 Actually, it's more generic than that- the inner struct can't access any
- Bill Baxter (17/60) Nov 05 2006 Odd. I could have sworn I saw there was a .outer property added in a
- BCS (4/21) Nov 05 2006 Accessing the outer class would require a pointer to it. The only way to...
- Bill Baxter (53/76) Nov 05 2006 I don't think so. Structs are always treated like plain old data. So
- Bill Baxter (36/122) Nov 05 2006 Ok ok. I was wrong. It is a little more complicated than that. If you...
- BCS (24/66) Nov 06 2006 another case where the constant offset assumption will fail
- Mariano (4/21) Nov 06 2006 This seams like really bad practice. A function inside a struct returnin...
- Karen Lanrap (2/4) Nov 06 2006 If it is bad practice, then why it is supported on the module level?
- Bill Baxter (14/20) Nov 06 2006 It's also exactly the kind of thing iterators are going to have to do.
class C { struct S { uint data; } S s; struct T { uint f() { return s.data; // this for s needs to be type C not type T * } } } void main(){}
Nov 05 2006
Karen Lanrap wrote:class C { struct S { uint data; } S s; struct T { uint f() { return s.data; // this for s needs to be type C not type T * } } } void main(){}Actually, it's more generic than that- the inner struct can't access any member variable of the outer class: class C { uint s; struct T { uint f() { return s; // this for s needs to be type C not type T * } } } void main(){} I'm not certain if this is a bug or if there is a good reason for this. -- ~John Demme me teqdruid.com http://www.teqdruid.com/
Nov 05 2006
John Demme wrote:Karen Lanrap wrote:Odd. I could have sworn I saw there was a .outer property added in a recent version. Apparently it only applies to inner classes, not structs. This compiles: class C { uint s; class T { uint f() { return this.outer.s; } } } void main(){} --bbclass C { struct S { uint data; } S s; struct T { uint f() { return s.data; // this for s needs to be type C not type T * } } } void main(){}Actually, it's more generic than that- the inner struct can't access any member variable of the outer class: class C { uint s; struct T { uint f() { return s; // this for s needs to be type C not type T * } } } void main(){} I'm not certain if this is a bug or if there is a good reason for this.
Nov 05 2006
Accessing the outer class would require a pointer to it. The only way to get that pointer would be to add a hidden value to the struct. In D, structs are bare bones aggregates without any hidden stuff added in. == Quote from Karen Lanrap (karen digitaldaemon.com)'s articleclass C { struct S { uint data; } S s; struct T { uint f() { return s.data; // this for s needs to be type C not type T * } } } void main(){}
Nov 05 2006
BCS wrote:Accessing the outer class would require a pointer to it. The only way to get that pointer would be to add a hidden value to the struct. In D, structs are bare bones aggregates without any hidden stuff added in. == Quote from Karen Lanrap (karen digitaldaemon.com)'s articleI don't think so. Structs are always treated like plain old data. So in memory this: class C { int a; int b; } has exactly the same layout as class C { int a; struct S { int b; } S s; } Therefore, if it is possible for S to compute the address to it's own members: class C { int a; struct S { int b; int f() { return b+1; } } S s; } Then it should also be possible for S to compute the address of members in the outer class at compile time. Try running this program: ------------ import std.stdio : writefln; class C { int a; struct S { int b; int outer_a() { return cast(int)* (cast(char*)(&b)-int.sizeof); } } S s; } void main() { C c = new C; c.a = 42; writefln("c.a's value is ", c.s.outer_a()); } --------------- The offset to the members of the outer class (or outer struct) are compile time constants. It's well within the compiler's ability to compute them. --bbclass C { struct S { uint data; } S s; struct T { uint f() { return s.data; // this for s needs to be type C not type T * } } } void main(){}
Nov 05 2006
Bill Baxter wrote:BCS wrote:Ok ok. I was wrong. It is a little more complicated than that. If you have two instances of S inside the class, then you'd need two instances of the method outer_a, each with it's own compile time offsets. But then something like outer_a() { static int num_calls++; ... } would fail. One solution would be to add the hidden pointer-to-outer member to any structs that use the "outer" property. If you don't use it, you don't pay for it. Rather like how virtual functions are handled in C++. If you don't declare any methods to be virtual, then the compiler doesn't generate a vtable. In the mean time, the obvious workaround is to give the structs a pointer to the outer class yourself. class C { int a; this() { s.outer = this; s2.outer = this; } struct S { int b; int whats_A() { this.b += 1; return outer.a; } C outer; } S s; S s2; } --bbAccessing the outer class would require a pointer to it. The only way to get that pointer would be to add a hidden value to the struct. In D, structs are bare bones aggregates without any hidden stuff added in. == Quote from Karen Lanrap (karen digitaldaemon.com)'s articleI don't think so. Structs are always treated like plain old data. So in memory this: class C { int a; int b; } has exactly the same layout as class C { int a; struct S { int b; } S s; } Therefore, if it is possible for S to compute the address to it's own members: class C { int a; struct S { int b; int f() { return b+1; } } S s; } Then it should also be possible for S to compute the address of members in the outer class at compile time. Try running this program: ------------ import std.stdio : writefln; class C { int a; struct S { int b; int outer_a() { return cast(int)* (cast(char*)(&b)-int.sizeof); } } S s; } void main() { C c = new C; c.a = 42; writefln("c.a's value is ", c.s.outer_a()); } --------------- The offset to the members of the outer class (or outer struct) are compile time constants. It's well within the compiler's ability to compute them. --bbclass C { struct S { uint data; } S s; struct T { uint f() { return s.data; // this for s needs to be type C not type T * } } } void main(){}
Nov 05 2006
Bill Baxter wrote:Bill Baxter wrote:[...]Ok ok. I was wrong. It is a little more complicated than that. If you have two instances of S inside the class, then you'd need two instances of the method outer_a, each with it's own compile time offsets. But then something like outer_a() { static int num_calls++; ... } would failanother case where the constant offset assumption will fail class C { int a; struct S { int b; int f() { return b+1; } int outer_a() { return cast(int)* (cast(char*)(&b)-int.sizeof); } /*static*/ void other() { S foo; foo.outer_a(); S* bar; bar.outer_a(); } }One solution would be to add the hidden pointer-to-outer member to any structs that use the "outer" property. If you don't use it, you don't pay for it. Rather like how virtual functions are handled in C++. If you don't declare any methods to be virtual, then the compiler doesn't generate a vtable.Ouch, I am a big fan of the "struct are just data" approach. I would rather, on the rare occasion this would be used, give up a bit of speed and go with objects than add hidden overhead to structs.In the mean time, the obvious workaround is to give the structs a pointer to the outer class yourself. class C { int a; this() { s.outer = this; s2.outer = this; } struct S { int b; int whats_A() { this.b += 1; return outer.a; } C outer; } S s; S s2; }That would also be a good solution
Nov 06 2006
== Quote from Karen Lanrap (karen digitaldaemon.com)'s articleclass C { struct S { uint data; } S s; struct T { uint f() { return s.data; // this for s needs to be type C not type T * } } } void main(){}This seams like really bad practice. A function inside a struct returning something from outside itself? M.
Nov 06 2006
Mariano wrote:This seams like really bad practice. A function inside a struct returning something from outside itself?If it is bad practice, then why it is supported on the module level?
Nov 06 2006
Karen Lanrap wrote:Mariano wrote:It's also exactly the kind of thing iterators are going to have to do. class C { class MyIterator { int get() { return .outer.array[i]; } ... size_t i=0; } int[] array; } --bbThis seams like really bad practice. A function inside a struct returning something from outside itself?If it is bad practice, then why it is supported on the module level?
Nov 06 2006