How can I get this UDA at compile time?

Jacob Carlborg doob at me.com
Sun Feb 21 09:30:14 UTC 2021


On 2021-02-21 07:12, Jack wrote:
> I've had a struct like this:
> 
> struct Attr
> {
>      string value;
> }
> 
> struct Foo
> {
>      @(Attr("a attr"))
>      enum a = Foo(10);
> 
>      @(Attr("b attr"))
>      enum b = Foo(11);
> 
> 
>      int x;
>      int y;
>      bool doY = true;
> 
>      int value()
>      {
> 
>          return x;
>      }
> 
> }
> 
> I'd like to get that atrribute's value at compile time, something like 
> this:
> 
>      enum s = Foo.a.baa;
>      enum s2 = Foo.b.baa;
>      writeln(s); // a attr
>      writeln(s2); // b attr
> 
> I did this:
> 
>      string baa()
>      {
>          import std.traits : getUDAs, hasUDA;
> 
>          static foreach(field; __traits(allMembers, Foo))
>          {{
>              alias m = __traits(getMember, Foo, field);
>              static if(is(typeof(m) == Foo))
>              {
>                  if(m.value == this.value)
>                      return getUDAs!(m, Attr)[0].value;
>              }
>          }}
> 
>          return null;
>      }
> 
> that was working fine, but I needed to switch value property from Foo 
> struct, so that I can't read this value at CTFE anymore, so this fails now:
> 
>              if(m.value == this.value)
>                      return getUDAs!(m, Attr)[0].value;
> 
> How can I solve this?

You can't look at the value when trying to find the correct member. You 
need to look at the name. I don't think it's possible to solve that with 
the exact same API as you have used above. The simplest solution would 
be to just use `__traits(getAttributes)` and wrap that in a help function:

string getAttribute(T, string name)()
{
      return __traits(getAttributes, mixin(T.stringof, ".", name))[0].value;
}

void main()
{
     writeln(getAttribute!(Foo, "a"));
}

Or you can create a proxy struct and use opDispatch like this, to get 
something a bit closer to your original example:

// add this to the Foo struct
static Proxy attributes()
{
     return Proxy();
}

struct Proxy
{
     string opDispatch(string name)()
     {
         return __traits(getAttributes, mixin("Foo.", name))[0].value;
     }
}

void main()
{
     writeln(Foo.attributes.a);
}

-- 
/Jacob Carlborg


More information about the Digitalmars-d-learn mailing list