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