static foreach over enum symbols

Boris Carvajal boris2.9 at gmail.com
Sat Feb 15 12:08:41 UTC 2020


On Friday, 14 February 2020 at 22:24:14 UTC, Ben Jones wrote:
> Hi all,
>
> I'm getting unexpected results while trying to process symbols 
> from a module, some of which are enums.
>
> Depending on whether or not I comment out the first static 
> foreach loop below, fullyQualifiedName gives me different 
> results in the second loop.
>
> In either case, I'm surprised I can't grab the UDAs in the 
> second static foreach loop.  Any ideas what's going on?
>
> Test case:
> ---a.d---
> module a;
>
> @Object
> enum x = "hello";
>
> @Object
> enum y = "goodbye";
>
> @Object
> struct z{}
>
>
> ---main.d---
>
> template symbols(alias Mod){
>     import std.meta;
>     alias toSymbol(alias T) = __traits(getMember, Mod, T);
>     alias symbols = staticMap!(toSymbol, __traits(allMembers, 
> Mod));
> }
>
>
> void main(){
>     import std.traits;
>     import std.meta;
>     import a;
>     //commenting this out changes the results below
>     static foreach(sym; symbols!a){
>         pragma(msg, fullyQualifiedName!sym);
>         pragma(msg, __traits(getAttributes, sym));
>     }
>
>     pragma(msg, "\nget with UDAs\n");
>     pragma(msg, getSymbolsByUDA!(a, Object));
>     alias udaSyms = getSymbolsByUDA!(a, Object);
>     pragma(msg, staticMap!(fullyQualifiedName, udaSyms));
>     static foreach(us; udaSyms){
>         pragma(msg, fullyQualifiedName!us);
>         pragma(msg, __traits(getAttributes, us));
>     }
> }
>
> ---
>
> annotated output of dmd main.d:
>
> with the first loop commented out:
>
> get with UDAs
>
> tuple("hello", "goodbye", (z))
> tuple("a.x", "a.y", "a.z")
> a.x
> tuple()  //why is the UDA gone?
> a.y
> tuple()
> a.z
> tuple((Object))
>
>
> and with the first loop:
>
> object
> tuple()
> main.main.sym  //it's not a.x anymore, it's the name of the 
> local var for static foreach?
> tuple()
> main.main.sym
> tuple()
> a.z
> tuple((Object))
>
> get with UDAs
>
> tuple("hello", "goodbye", (z))
> tuple("main.main.sym", "main.main.sym", "a.z") //and the 
> results are changed here too?
> main.main.sym
> tuple()
> main.main.sym
> tuple()
> a.z
> tuple((Object))

 From language spec [1]: "the name of the static foreach variable 
is bound to the i-th entry of the sequence, either as an enum 
variable declaration (for constants) or an alias declaration (for 
symbols).

Enums are treated differently, so your 'sym' is not an alias to 
the original enum but an enum itself with the same value. Because 
of that, fullyQualifiedName or any template with alias argument 
will just get the sym temporary not the enum from the symbols 
tuple.


This code should work:

static foreach(i, _; symbols!a){
          pragma(msg, fullyQualifiedName!(symbols!a[i]));
          // or manually aliased, but you need to use regular 
foreach or {{ }} to avoid redefinitions.
          alias sym = symbols!a[i];
          pragma(msg, fullyQualifiedName!sym);
       }


[1] https://dlang.org/spec/version.html#staticforeach


More information about the Digitalmars-d-learn mailing list