Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 05, 2006 Why no acess to other structs in classes? | ||||
---|---|---|---|---|
| ||||
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(){} |
November 05, 2006 Re: Why no acess to other structs in classes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Karen Lanrap | 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/ |
November 05, 2006 Re: Why no acess to other structs in classes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Demme | John Demme wrote:
> 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.
>
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(){}
--bb
|
November 05, 2006 Re: Why no acess to other structs in classes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Karen Lanrap | 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 article
> 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(){}
|
November 05, 2006 Re: Why no acess to other structs in classes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to BCS | 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 article
>> 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(){}
>
I 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.
--bb
|
November 06, 2006 Re: Why no acess to other structs in classes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | Bill Baxter wrote:
> 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 article
>>> 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(){}
>>
>
> I 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.
>
> --bb
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;
}
--bb
|
November 06, 2006 Re: Why no acess to other structs in classes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Karen Lanrap | == Quote from Karen Lanrap (karen@digitaldaemon.com)'s article
> 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(){}
This seams like really bad practice. A function inside a struct returning something from outside itself?
M.
|
November 06, 2006 Re: Why no acess to other structs in classes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | 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 fail another 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 |
November 06, 2006 Re: Why no acess to other structs in classes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mariano | 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?
|
November 06, 2006 Re: Why no acess to other structs in classes? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Karen Lanrap | Karen Lanrap wrote:
> 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?
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;
}
--bb
|
Copyright © 1999-2021 by the D Language Foundation