data-oriented struct abstraction ?

Michael Coulombe via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun May 31 18:25:41 PDT 2015


On Saturday, 30 May 2015 at 15:06:16 UTC, short2cave wrote:
> Yes, kind of. The template should be able to generate the 
> accessors using the fields of the struct passed as template 
> argument. But also a special accessor wich returns all the 
> items accessors, in a structured way:
>
>
> ---
> struct Model
> {
>    uint a, b;
> }
>
> template Structured(T)
> {
>     alias Structured = ...;
> }
> ---
>
> allowing things like:
> ---
> Structured!Model sm;
>
> sm[0].a = 0;
> sm[0].b = 0;
> auto item = sm[0];
> sm.a = 0;
> sm.pushBack;
> auto item = sm.back;
> sm.length += 1,
> ---
> etc.

Proof of concept:

import std.stdio, std.string, std.typetuple, std.traits, 
std.container;
private auto genIndexerCode(string[] memberNames) {
     enum f = `@property auto ref %s() { return 
__parent.members[%s][__index]; }`;
     string s = "";
     foreach(i, member ; memberNames) {
         s ~= format(f, member, i);
     }
     return s;
}
class ArrayOf(S) if (is(S == struct) && !isNested!S) {
private:
     alias memberNames = FieldNameTuple!S;
     alias memberTypes = FieldTypeTuple!S;
     staticMap!(Array, memberTypes) members;
     static struct Indexer {
     private:
         ArrayOf!S __parent;
         size_t __index;
     public:
         S __get() {
             S copy;
             foreach(member ; memberNames) {
                 mixin(`copy.%s = this.%s;`.format(member,member));
             }
             return copy;
         }
         alias __get this;
         void opAssign(S src) {
             foreach(member ; memberNames) {
                 mixin(`this.%s = src.%s;`.format(member,member));
             }
         }
         mixin(genIndexerCode([memberNames]));
     }
public:
     this() {}
     auto opIndex(size_t i) {
         return Indexer(this, i);
     }
     void insertBack(S s) {
         foreach(i, mem ; memberNames) {
             mixin(`members[%s].insertBack(s.%s);`.format(i, mem));
         }
     }
}
struct Test {
     int x;
     string y;
}
unittest {
     auto aos = new ArrayOf!Test();
     aos.insertBack(Test(5, "hi"));
     aos[0].x = -7;
     aos.insertBack(Test.init);
     aos[1] = Test(11,"boo");
     assert(aos[0] == Test(-7,"hi"));
     assert(aos[1] == Test(11,"boo"));
}


More information about the Digitalmars-d-learn mailing list