On Saturday, 13 June 2015 at 10:01:45 UTC, JDemler wrote:
Hey,

i am trying to wrap my head around __traits.

One thing i just do not understand is following:

struct S{
   string member1;
   int member2;
}

void main(string[] args)
{
   foreach(typeStr; __traits(allMembers, S))
   {
     auto tp = __traits(getMember, S, typeStr);
     static if (__traits(isArithmetic, tp))
       writeln(typeStr ~ " is Arithmetic");
   }
}

Does not compile. "main.d(15): Error: need 'this' for 'member1'
of type 'string'"

But if the inner part of the foreach-loop is changed to:

static if (__traits(isArithmetic, __traits(getMember, S,
typeStr)))
       writeln(typeStr ~ " is Arithmetic");

it compiles and does exactly what i expect it to do.

If i understand it correctly __traits(getMember returns a
reference to that member, so i get why i shouldn't be able to use
it with the class instead of an instance of a class.

But why does it work if it is nested inside a __traits call?

"auto tp" is treating a runtime variable, but you don't have an actual instance of S. What you want is an alias of the symbol without creating an instance.

Unfortunately alias tp = __traits(getMember, S, typeStr); doesn't work, but if you steal* Alias from std.typetuple(or std.meta, if you're running a very recent dmd build) then you can do

alias tp = Alias!(__traits(getMember, S, typeStr));

and then it will work for you.

*for some reason it's not public, but it's very short and simple:

template Alias(alias a)
{
    static if (__traits(compiles, { alias x = a; }))
        alias Alias = a;
    else static if (__traits(compiles, { enum x = a; }))
        enum Alias = a;
    else
        static assert(0, "Cannot alias " ~ a.stringof);
}
// types and tuples
template Alias(a...)
{
    alias Alias = a;
}

unittest
{
    enum abc = 1;
    static assert(__traits(compiles, { alias a = Alias!(123); }));
    static assert(__traits(compiles, { alias a = Alias!(abc); }));
    static assert(__traits(compiles, { alias a = Alias!(int); }));
static assert(__traits(compiles, { alias a = Alias!(1,abc,int); }));
}

Reply via email to