Could you please review the following template to see whether it makes sense. It produces an AliasSeq type consisting of the default values of the members of a struct. It should and does support members that are initialized with '= void'. I could not achieve this with std.traits or __traits.

However, I'm not that happy with the use of __traits(compiles) below. Can this be improved?

Thank you,
Ali


import std.meta;

/** Get as an expression tuple the default values of members of a struct. */
template MemberDefaults(T) {
    static if (!is(T == struct)) {
        static assert(T.stringof ~ " is not a struct type");
    }

    import std.traits : FieldNameTuple;
    enum t = T.init;
    alias fields = FieldNameTuple!T;

    template get(size_t i) {
        static if (__traits(compiles, { enum _ = t.tupleof[i]; })) {
            enum get = t.tupleof[i];
        }
        else {
            alias get = void;
        }
    }

    template Impl(size_t i = 0) {
        import std.meta : AliasSeq;
        static if (i == fields.length) {
            alias Impl = AliasSeq!();
        } else {
            alias Impl = AliasSeq!(get!i, Impl!(i+1));
        }
    }

    alias MemberDefaults = Impl!();
}

unittest {
    struct S {
        int i = 42;
        string s = "hello";
        char c = 'c';
    }

    static assert(MemberDefaults!S == AliasSeq!(42, "hello", 'c'));
}

unittest {
    struct S {
        int i = 42;
        int j = void;
    }

    static assert(MemberDefaults!S[0] == 42);
    static assert(is(MemberDefaults!S[1] == void));
}

void main() {
}
  • MemberDefaults trait Ali Çehreli via Digitalmars-d-learn

Reply via email to