__traits getMember is context sensetive?

John Colvin via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Jun 13 03:36:39 PDT 2015


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


More information about the Digitalmars-d-learn mailing list