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"));
}

Reply via email to