Thread overview
Getting Field Names of a specific UDA in compile time.
Oct 03, 2020
realhet
Oct 03, 2020
Adam D. Ruppe
Oct 03, 2020
realhet
October 03, 2020
Hi,

class Printer{
  @("NODES") int gem1, gem2, gem3, gem4, gem5, head1, head2, head3, head4;

  import std.traits, std.meta;
  alias Nodes = getSymbolsByUDA!(typeof(this), "NODES");
  enum NodeNames = ["gem1", "gem2", ....];
}

Is there a way to make an enum like the above with compile time programming?
I only managed to get the string[] by making a static foreach, but I don't know how to put that in an enum xxx = ...; statement.
October 03, 2020
On Saturday, 3 October 2020 at 13:10:31 UTC, realhet wrote:
> I only managed to get the string[] by making a static foreach, but I don't know how to put that in an enum xxx = ...; statement.

There's always other ways but general rule: if you can get it one way, just wrap that up in a function and call that function for your enum initializer.

string[] your_function() {
     // implementation here you already have
     return it;
}

enum NodeNames = your_function();


Though with arrays btw `static immutable` tends to give better results than `enum` since it avoids extra allocations.
October 03, 2020
On Saturday, 3 October 2020 at 14:00:30 UTC, Adam D. Ruppe wrote:
> On Saturday, 3 October 2020 at 13:10:31 UTC, realhet wrote:
>> I only managed to get the string[] by making a static foreach, but I don't know how to put that in an enum xxx = ...; statement.
>
> There's always other ways but general rule: if you can get it one way, just wrap that up in a function and call that function for your enum initializer.
>
> string[] your_function() {
>      // implementation here you already have
>      return it;
> }
>
> enum NodeNames = your_function();
>
>
> Though with arrays btw `static immutable` tends to give better results than `enum` since it avoids extra allocations.

I tried it to put into a function:

auto getSymbolNamesByUDA(T, string uda)(){
    string[] res;
    static foreach(a; getSymbolsByUDA!(T, uda)) res ~= a.stringof;
    return res;
}

class Printer{
    @("NODES") int gem1, gem2, gem3, gem4, gem5, head1, head2, head3, head4;
    alias Nodes = getSymbolsByUDA!(typeof(this), "NODES");
    enum NodeNames = getSymbolNamesByUDA!(typeof(this), "NODES");
}

void main(){
    static foreach(n; Printer.Nodes) n.stringof.writeln;
    Printer.NodeNames.writeln;
}

Up until this point, the alias declaration was before the enum declaration.
It gives an error:
Error: unknown, please file report on issues.dlang.org

But now I tried to comment out the alias declaration and it worked. It also works when I put the alias declaration after the enum:
    enum NodeNames = getSymbolNamesByUDA!(typeof(this), "NODES");
    alias Nodes = getSymbolsByUDA!(typeof(this), "NODES");

Same behavior with "static immutable".
My initial intention was to use the Nodes alias to get the name strings out of it. Now it needs more copy paste but it works.

This is weird o.O

Thank you!
October 03, 2020
On 10/3/20 10:16 AM, realhet wrote:

> I tried it to put into a function:
> 
> auto getSymbolNamesByUDA(T, string uda)(){
>      string[] res;
>      static foreach(a; getSymbolsByUDA!(T, uda)) res ~= a.stringof;
>      return res;
> }

D __traits give you strings, the std.traits thing is giving you symbols. Don't use it, just use the compiler traits:

// note, not tested
auto getSymbolNamesByUDA(T, string uda)(){
     string[] res;
     static foreach(n; __traits(allMembers, T)) {
        // static, but don't use static foreach so you can break
	foreach(u; __traits(getAttributes, __traits(getMember, T, n))
           static if(is(typeof(u) == string) && u == uda) {
               res ~= n;
               break;
           }
     }
     return res;
}

-Steve