On 10/10/2016 04:50 PM, Ali Çehreli wrote:
> 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.

Reviving this thread because I've realized that the template does not work for members that are structs themselves.

/** Get as an expression tuple the default values of members of a struct. */
template MemberDefaults(T) {
    static assert (is(T == struct), 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 get = 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!();
}

struct Foo {
    string s;
    int i;
}

unittest {
    struct S {
        int i = 42;
        string s = "hello";
        char c = 'c';
        int j = void;
        Foo foo0;
        Foo fooVoid = void;
    }

    alias result = MemberDefaults!S;

    import std.meta : AliasSeq;
    if (!is(result == AliasSeq!(42, "hello", 'c', void, Foo, void))) {
        pragma(msg, "Did not match: ", result);
        static assert(false);
    }
}

void main() {
}

Here is the output of a -unittest compilation:

  Did not match: tuple(42, "hello", 'c', (void), Foo(null, 0), Foo(, ))

Notice how the j member worked as expected: Its default value appeared as (void) in the result. (Aside: It's strange that pragma(msg) parenthesizes it.)

The problem is, the default value of the fooVoid member does not appear as void but as "Foo(, )". This seems to be a compiler bug to me. One might parse that string as a workaround but then it wouldn't work for empty structs. (Although, empty structs could be excluded by this template. Hmmm... That might work.)

Can you make this work? i.e. Can you make the result be

  AliasSeq!(42, "hello", 'c', void, Foo, void)

Is it possible to detect members that are void-initialized at all?

Ali

Reply via email to