[static] foreach scope, template declaration ?

SlomoTheBrave via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Thu Sep 25 16:08:52 PDT 2014


On Thursday, 25 September 2014 at 22:11:20 UTC, Mathias LANG 
wrote:
> I'm a bit puzzled with the following behavior:
>
> ----
> import std.typetuple, std.traits;
>
> struct UDAStruct {
>     string identifier;
> }
>
> class MyClass {
>     @(UDAStruct("p1"), UDAStruct("p2"), UDAStruct("P3")) // P3 
> is a typo
>       void func(int p1, string p2, float p3) {}
> }
>
> unittest {
>     alias Func = MyClass.func;
>     enum ParamNames = ParameterIdentifierTuple!Func;
>     enum ParamAttr = __traits(getAttributes, Func);
>
>     foreach (attr; ParamAttr) {
>         template CmpName(string PName) {
>             pragma(msg, "Instantiated for: "~PName);
>             enum CmpName = (PName == attr.identifier);
>         }
>         pragma(msg, "Current attr is: "~attr.identifier);
>         static assert(anySatisfy!(CmpName, ParamNames));
>     }
>
>     // Foreach does introduce a scope, as this produce no 
> compile time error.
>     template CmpName(string test) { enum CmpName = test; }
>     static assert(CmpName!"?" == "?");
> }
>
> void main() {}
> ----
>
> The output is (FE 2.066 & 2.065 tested):
> 148 geod24 at barsoom2 ~ % dmd -unittest -run test.d
> Current attr is: p1
> Instantiated for: p1
> Instantiated for: p2
> Instantiated for: p3
> Current attr is: p2
> Current attr is: P3
>
> Obviously one call tell it's not what I expected. It looks like 
> DMD is reusing the instantiations of the template of the first 
> loop for p2 and P3.
> The 2 lines at the end check that foreach does introduce a 
> scope, but it behaves differently than what we're use to.
>
> Is there a way around this ?
> I tried to move CmpName outside the loop, then declare `alias 
> Cmp(string x) = CmpName(attr, x);` in the loop, but it doesn't 
> help (I guess the same thing happens?).

a way around this is not to use anySatisfy nor the template, for 
example this works as expected:

import std.typetuple, std.traits;

struct UDAStruct {
     string identifier;
}

class MyClass {
     @(UDAStruct("p1"), UDAStruct("p2"), UDAStruct("P3")) // P3 
isa typo
       void func(int p1, string p2, float p3) {}
}

------
void main(string[] args){

     alias Func = MyClass.func;
     enum ParamNames = ParameterIdentifierTuple!Func;
     enum ParamAttr = __traits(getAttributes, Func);

     foreach(i,attr; ParamAttr) {
         static assert(attr.identifier == ParamNames[i], 
attr.identifier);
     }
}
------

which is less abstruse. However I don't know if it has hurted 
your eyes too but the output lines order shows there is a problem 
too:

> Current attr is: p1
> Instantiated for: p1
> Instantiated for: p2
> Instantiated for: p3
> Current attr is: p2
> Current attr is: P3

instead of

> Current attr is: p1
> Instantiated for: p1
> Current attr is: p2
> Instantiated for: p2
> Current attr is: P3
> Instantiated for: p3

o!o


More information about the Digitalmars-d-learn mailing list