MemberDefaults trait

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Mar 14 19:06:54 PDT 2017


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



More information about the Digitalmars-d-learn mailing list