How can I get this UDA at compile time?
Jack
jckj33 at gmail.com
Sun Feb 21 20:07:06 UTC 2021
On Sunday, 21 February 2021 at 09:30:14 UTC, Jacob Carlborg wrote:
> 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.
It doesn't work when the value is unique and know at
compile-time, as it was previously. So this worked:
>> 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;
>> }
>> }}
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.
> 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'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"));
> }
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.
More information about the Digitalmars-d-learn
mailing list