www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Getting Field Names of a specific UDA in compile time.

reply realhet <real_het hotmail.com> writes:
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.
Oct 03 2020
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
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.
Oct 03 2020
parent reply realhet <real_het hotmail.com> writes:
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!
Oct 03 2020
parent Steven Schveighoffer <schveiguy gmail.com> writes:
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
Oct 03 2020