digitalmars.D.learn - How can I get this UDA at compile time?
- Jack (47/47) Feb 20 2021 I've had a struct like this:
- Jacob Carlborg (33/95) Feb 21 2021 You can't look at the value when trying to find the correct member. You
- Jack (57/164) Feb 21 2021 It doesn't work when the value is unique and know at
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?
Feb 20 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
Feb 21 2021
On Sunday, 21 February 2021 at 09:30:14 UTC, Jacob Carlborg wrote:On 2021-02-21 07:12, Jack wrote:It doesn't work when the value is unique and know at compile-time, as it was previously. So this worked: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.This could retrieve the attribute at compile time by value but i did changes in the struct and the member value wasn't know at compile time anymore.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; } }}You need to look at the name.That's I'm looking for. Is there a way to get the idenfifier of the current instance, from within the class? for example: struct Foo { enum x = Foo(10); enum y = Foo(11); string myID() { eum s = some magic with traits? return s; } } writeln(Foo.x.myID); // x writeln(Foo.y.myID); // y that would solve my problem, I would just pass that idenfifier to __traits(getMember, Foo, x) then get what I want with getUDAs() I don't think it'spossible 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")); }the main isssue is get "a" identifier, as I mentioned previously.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); }your proxy struct and opDispatch() give me a good idea how do that, something like this: void main() { writeln(P.Foo); } struct S { string name; } struct P { static auto ref opDispatch(string member)() { writeln("member = ", member); // save this somewhere alias m = __traits(getMember, A, member); return m; } } struct A { (S("attr foo")) enum Foo = A(10); (S("attr baa")) enum Baa = A(11); int v; } now I got the member string but I still need to figure out where to salve it to use from within the A struct. add a string id to struct A wouldn't work for Foo and Baa because they are enum. I have to save it somewhere else. I static array doesn't work either because it isn't run at CTFE.
Feb 21 2021