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