Re: How can I get this UDA at compile time?

2021-02-21 Thread Jack via Digitalmars-d-learn

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.





Re: How can I get this UDA at compile time?

2021-02-21 Thread Jacob Carlborg via Digitalmars-d-learn

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


How can I get this UDA at compile time?

2021-02-20 Thread Jack via Digitalmars-d-learn

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?