December 20, 2012
On 12/18/2012 04:42 AM, js.mdnq wrote:
> It looks like the approach 2 does what I'm looking for pretty nicely
> except that, If I'm not mistaken the user struct will error out when
> trying to access members from the master.

Another approach that works: http://dpaste.dzfl.pl/966d9f3a
(could have been very simple if ``multiple alias this'' was available).

regards,
r_m_r

December 21, 2012
On Thursday, 20 December 2012 at 04:17:48 UTC, r_m_r wrote:
> On 12/18/2012 04:42 AM, js.mdnq wrote:
>> It looks like the approach 2 does what I'm looking for pretty nicely
>> except that, If I'm not mistaken the user struct will error out when
>> trying to access members from the master.
>
> Another approach that works: http://dpaste.dzfl.pl/966d9f3a
> (could have been very simple if ``multiple alias this'' was available).
>
> regards,
> r_m_r

I see what you are doing and it is a possible good approach. There are 2 issues I have with it:

1. Wrapping the members could be a performance hit if D does not inline. This isn't so much of an issue with the method but of D as it seems not to inline well. It's really not a big deal though at this point.

2. More serious is the inability to access elements from one struct in another.  E.g., You should have some way to access S_A's members from S_B. This is difficult to do properly though since S_B generally shouldn't know about S_A.

You can insert a reference to A inside B to do this, and this leads to the same issues I came across with nested structs. You end up not needing that ptr in the composite class(your S_ABC) since everything is offset from each other. So you could go down the route I went(or try and some up with another solution) to make this work.


For example, possibly a simpler way to do this is:

struct S_AB(bool _NestLevel)
{
    ...
    public:
       struct S_A(int _Offset) { S_B B_f() { 'return B;' } }
       struct S_B(int _Offset) { S_A A_f() { 'return A;' } }

    mixin S_A sA; mixin S_B sB;

    GenUnion(...)
}

Where GenUnion is your mixin technique that wraps all members of S_A and S_B. Basically combining our techniques. That way no extra pointers are wasted AND we have access to "siblings".

One problem with your method is it is more of a product rather than a union. A true union will allow duplicates and not store them. Technically we do not wrap the members but store everything in the composite class. Any "overlap" between the sub structures will produce only one "copy".

e.g.,

struct S_A { int x; }
struct S_B { int x; }

then GenUnion(S_A, S_B) will produce a struct like S_AB { int x; }

in your method, you have two x's.

Now it might be impossible to efficiently generate at true union in D at the moment and your method may be the only possibility(which, is more of a product).   If we could get a the struct's code rather than just the member declarations then it would be rather easy.

struct S_A { int x; int y; void func(); void funcA(); }
struct S_B { int x; int z; void func(); void funcB(); }

then GenUnion(S_A, S_B) will produce a struct like
S_AB
{
   int x;
   int y;
   void func();
   void funcA();
   void funcB();
}

Note that S_AB does not waste space. size(S_AB) < size(S_A) + size(S_B). Issues may arise if, say, S_A.func != S_B.func. Ways around this is to generate an error, warn, OR, we could use your method and has "perspectives"

e.g.,


S_AB()
{
   string Perspective = "A";
   S_A sA; S_B sB;
   ...
   void func() { if (Perspective == "A") sA.func(); else sB.func(); }
   ...
}


In which case we have sort of run-time polymorphism(or you could make it compile time by using a static if instead). S_AB can change it's behavior just by setting the "perspective". This could be lead to problems conceptually since we generally do not think of structs behaving like this.

It would, though, make more GenStruct more union like since the wrappers are not qualified(which produces a more product like structure).

I think, but not totally sure, that the above method of perspectives is essentially a sort of of set "inheritance"(not parent child but through siblings though),

For example, if A is human and B is mammal the S_AB can be made to be a human or a mammal by setting it's "perspective" but it's it's really a union one can have unrelated things, so it is not quite the same thing as inheritance. It may be useful to create variant types since or possibly other things.

In any case, I think your on the right track to be able to get something useful out of it. I think, though, your limited to what you can achieve because of D's limitations of getting the code of things.

For me, the two things I would need from your method to use is: 1. True union like behavior(it's ok to wrap but do not over qualify the member names). 2. The ability to access siblings without storing additional ptr's(I'm not sure if this is possible without access to the method code, my method of offsets might not work with a true union because it could change the struct's memory layout).

Thanks for your work.



December 21, 2012
On 12/21/2012 07:18 AM, js.mdnq wrote:
> struct S_A { int x; int y; void func(); void funcA(); }
> struct S_B { int x; int z; void func(); void funcB(); }
>
> then GenUnion(S_A, S_B) will produce a struct like
> S_AB
> {
>     int x;
>     int y;
      int z; //did u miss this? ;)
>     void func();
>     void funcA();
>     void funcB();
> }

check this: http://pastebin.com/BQW7DtSD

struct S_A { int x; int y; void func() { x = 2*x; }; void funcA() { }; }
struct S_B { int x; int z; void func() { x = 3*x; }; void funcB() { }; }

void main()
{
    import std.stdio: writeln;

    mixin (Gen!("S_AB", S_A, S_B));
    pragma(msg, __traits(allMembers, S_AB));
    //prints: tuple("_s0","_s1","x","y","func","funcA","z","funcB")

    S_AB s_ab;
    s_ab.x = 10;
    s_ab.func();
    assert(s_ab.x == 20);
}

BTW what you are trying to achieve with your GenUnion(S_A, S_B) may require functionality currently missing in D (as you've already mentioned). For example, I can generate a struct with the fields from the two structs S_A and S_B like so:

struct S_AB
{
    int x;
    int y;
    int z;
    void func() { } ; //note the empty function body
    void funcA() { } ;
    void funcB() { };
}

but it will be useless since AFAIK I cannot get a stringof S_A.func()'s body at compile time.

One alternative as I've shown is to generate a struct with hidden fields and properties (until 'multiple alias this' functionality gets implemented) which will atleast behave like your GenUnion(S_A, S_B) struct (from a user perspective).

BTW if you find any interesting alternative, please consider adding it to the dwiki - http://wiki.dlang.org/ (for e.g.: http://wiki.dlang.org/Combining_Structs)

regards,
r_m_r


December 21, 2012
On 12/21/2012 10:30 AM, r_m_r wrote:
> http://wiki.dlang.org/Combining_Structs)

the link should be: http://wiki.dlang.org/Combining_structs

regards,
r_m_r
1 2 3 4 5
Next ›   Last »