View mode: basic / threaded / horizontal-split · Log in · Help
December 09, 2012
struct in class feature
stemming from:

http://forum.dlang.org/thread/azqevtjaoafbapiadgjz@forum.dlang.org

I believe the following idea would offer good benefit for 
encapsulation in classes(increases the divide and conquer 
approach):

For structs in classes(call them cstructs if you want):

prototype:

class A
{
    cstruct B // Can only be used inside class A
    {
        int x;
        void func()
        {
            // if func accesses any member of A then a hidden 
"cthis" is passed to it to allow it to look them up
            a = x*45;
        }
    }

    B b;
    int a;
}

A `cstruct` then, is useful for encapsulating data and 
functionality in a class into smaller self-contained parts. It 
would be very useful because it allows us to avoid collisions.


class A
{
    cstruct B
    {
        opAssign;
    }

    opAssign;
}

even though, functionally both opAssigns accept the same this 
pointer.

The reason being is that since a cstruct is fixed inside class 
A(any value type of type cstruct has a fixed offset from the 
start of class A), all the fields of both the class and struct 
are calculated by simple offsets.

i.e., the struct this ptr is simply an offset from the class this 
ptr. This allows us to use one or the other but we don't need to 
store a ptr to a type A inside the struct to access is(and we can 
also get at the private members of A).

Having such a feature makes it easy to wrap types in a struct and 
provide custom  operator overloading but still being able to 
access the class members(which is not possible as it stands):

class A
{
    cstruct sInfo
    {
        void print() { writeln(Name); }
    }

    string Name;
    sInfo Info;

    void print() { writeln("It's howdy doody time!"); }
}


This not also provides better encapsulation it also avoids 
collisions. The above case is easily fixed but it is impossible 
to do for build in overloads since we can't specify the type we 
want to overload(it works on the class, not a member of a class):

e.g., the above can be written as
class A
{

    string Name;
    void printInfo() { writeln(Name); }
    void print() { writeln("It's howdy doody time!"); }
}

If one wants(although, we lose the hierarchy potential).

But what about

class A
{
    cstruct B
    {
        opAssign(int) { writeln("Inside " ~ Name); ... }
    }
    string Name;
    B b;
    opAssign
}

Both a and b have their own opAssigns, b's opAssign can access 
A's members(without storing a ptr to an A). But we can't 
"flatten" the hierarchy like the first case:

class A
{


    string Name;
    int b;
    opAssign
    opAssign(int) { writeln("Inside " ~ Name); ... } // works on 
A, not int b!
}

One can say that all we need to do to get such functionality is 
store a ptr of type A and set it in the structs. This is a huge 
waste of memory though and not necessary since we can just pass a 
"this"(cthis) ptr to the methods inside.

Obviously such structs can only be used in fields inside the 
class, not arbitrarily, and so are not quite the same thing as 
pass by value structs(which, when copied, would lose their 
relationship to their parent class). We would not allow a struct 
to be copied because then it would be disassociated from it's 
container object which would invalidate cthis.

(although we could convert it to a normal struct, one that 
doesn't use methods involving cthis and it should work just like 
any other struct... or "lift" the structs to include a this ptr 
inside that is used(but possibly create unintended consequences))

Any ideas if this is achievable or anything fundamentally wrong 
with it? My purpose for it is to provide additional functionality 
to fields inside classes but not have to include a this ptr in 
them for no reason. It is achievable using offsets and pointers 
but requires a lot of manual work that I feel the compiler could 
do easily.
December 11, 2012
Re: struct in class feature
Greetings

I too find this very useful. I am also having this situation often when
there is an array of nested struct instances inside a class environment.
This is a common scenario and deserves attention. Also I believe (looking
at D1 forums) that there was a time in the past when D1 nested structs did
support 'outer'.

But unfortunately structs are neglected part of D, so I am not sure if
developers give an ear to this thread. To make D truly a systems language
we need to make structs more robust and feature rich.

Regards
- Puneet
December 12, 2012
Re: struct in class feature
On Tuesday, 11 December 2012 at 03:28:00 UTC, d coder wrote:
> Greetings
>
> I too find this very useful. I am also having this situation 
> often when
> there is an array of nested struct instances inside a class 
> environment.
> This is a common scenario and deserves attention. Also I 
> believe (looking
> at D1 forums) that there was a time in the past when D1 nested 
> structs did
> support 'outer'.
>
> But unfortunately structs are neglected part of D, so I am not 
> sure if
> developers give an ear to this thread. To make D truly a 
> systems language
> we need to make structs more robust and feature rich.
>
> Regards
> - Puneet

If I want to manually pass the parent pointer to a child struct, 
how do I do it? The compiler won't allow me to use "this" from 
the parent until after the parent has been instantiated.

The solution I came up with is to create a default constructor 
for the parent that sets the child struct with the parents 
pointer. It works but maybe there's a better way?

BTW, the same situation happens with structs defined inside 
structs, they will not have access to the parent struct members 
unless you manually pass a pointer into the child struct at some 
point after the parent struct's address becomes known. You cannot 
create a default constructor for a struct, so reliably 
initializing the child struct with the parents pointer is 
problematic.

--rt
December 12, 2012
Re: struct in class feature
On Wednesday, 12 December 2012 at 01:36:55 UTC, Rob T wrote:
> On Tuesday, 11 December 2012 at 03:28:00 UTC, d coder wrote:
>> Greetings
>>
>> I too find this very useful. I am also having this situation 
>> often when
>> there is an array of nested struct instances inside a class 
>> environment.
>> This is a common scenario and deserves attention. Also I 
>> believe (looking
>> at D1 forums) that there was a time in the past when D1 nested 
>> structs did
>> support 'outer'.
>>
>> But unfortunately structs are neglected part of D, so I am not 
>> sure if
>> developers give an ear to this thread. To make D truly a 
>> systems language
>> we need to make structs more robust and feature rich.
>>
>> Regards
>> - Puneet
>
> If I want to manually pass the parent pointer to a child 
> struct, how do I do it? The compiler won't allow me to use 
> "this" from the parent until after the parent has been 
> instantiated.
>
> The solution I came up with is to create a default constructor 
> for the parent that sets the child struct with the parents 
> pointer. It works but maybe there's a better way?
>
> BTW, the same situation happens with structs defined inside 
> structs, they will not have access to the parent struct members 
> unless you manually pass a pointer into the child struct at 
> some point after the parent struct's address becomes known. You 
> cannot create a default constructor for a struct, so reliably 
> initializing the child struct with the parents pointer is 
> problematic.
>
> --rt

The problem with this method is that it requires an extra ptr in 
the child to the parent class. This is not necessary and a waste 
of space. While it work just fine it's not "efficient". Also, the 
compiler should have no issue accessing parent fields because 
they are a simple compile time const difference.

In some sense, if ptr_s is the this variable for a struct. Then 
ptr_s + x would point to a field in the struct. x is known at 
compile time as it depends on the size of the types in the 
struct. A nested struct would simply use ptr_s - y + z to access 
the elements of the parent. ptr_s - y = ptr_p, which is the this 
ptr to the parent class.

Hence, the only thing that would change is the compiler would 
have to compute where the struct is located in the class, then 
subtract that value from the struct's this ptr to get the this 
ptr of the parent object containing that struct object.

I wrote a post here that does something similar but ultimately 
the compiler can do it all for us and would not waste any space 
or extra cycles.

http://forum.dlang.org/thread/dgleowuonachabwxmlrx@forum.dlang.org

The main thing to realize is that the offsets are all known at 
compile time(obviously) and the relationship between a nested 
struct object and it's parent is also known at compile time. By 
having to "hard code" stuff to get it to work though, makes it 
difficult to manage.
Top | Discussion index | About this forum | D home