Why no acess to other structs in classes?

Bill Baxter dnewsgroup at billbaxter.com
Sun Nov 5 16:02:17 PST 2006


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 at 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



More information about the Digitalmars-d-learn mailing list