Re: Trying to understand something about UDAs.

2016-12-12 Thread Kevin Balbas via Digitalmars-d-learn

On Monday, 12 December 2016 at 19:56:27 UTC, Adam D. Ruppe wrote:

But the static if(is(UDA)) is probably what you actually want.


That's exactly what I was looking for, thanks.  I'm not sure I 
ever would've figured out that one on my own.


Re: Trying to understand something about UDAs.

2016-12-12 Thread Adam D. Ruppe via Digitalmars-d-learn

On Monday, 12 December 2016 at 19:37:42 UTC, Kevin Balbas wrote:
I'm trying to figure out how to test whether a UDA struct was 
initialized with arguments (and change the behavior of the 
surrounding code if it was.


Easy solution: test the type. @Attr is setting the type as a UDA, 
@Attr("test") is setting a *value* of type Attr.


static if(is(UDA)) {
  // UDA is a type, so it was @UDA
} else {
  // it is something else (do further tests to see if value, 
etc). For example, test is(typeof(UDA) == Attr) to see if it is a 
value of type Attr.

}


I can rationalize what the error means -- the compiler wasn't 
given a string so it requires a concrete object to get the 
member from.  What I don't understand is why *both* of those 
static ifs passed.  If it has the member and I can't get it, 
and if getting the member compiles yet at the same time it 
doesn't, I'm not sure how I can actually make this test work.


So you can get the member of a type, but not the value of that 
member. getMember itself succeeds - you can pass the result to 
further reflection things (test its type, offset, etc.), but you 
cannot get the value, which is what your code was trying to do 
there (that is like if you wrote `"foo";` in the middle of 
nowhere. It treats the string as an orphaned value).


Basically, getMember is legal, just not in the context you were 
trying it, thus the __traits(compiles) works but the next line 
doesn't.



But the static if(is(UDA)) is probably what you actually want.


Trying to understand something about UDAs.

2016-12-12 Thread Kevin Balbas via Digitalmars-d-learn
I'm trying to figure out how to test whether a UDA struct was 
initialized with arguments (and change the behavior of the 
surrounding code if it was.  While I was tinkering around with 
test files, I came up with this little gem:


import std.traits;

struct Attr
{
string str;
}

@Attr("test")
void foo(){}

@Attr
void bar(){}

void main()
{
alias UDA = getUDAs!(bar, Attr)[0];
static if (__traits(hasMember, UDA, "str"))
{
static if (__traits(compiles, __traits(getMember, UDA, 
"str")))

{
__traits(getMember, UDA, "str"); // Compile error! 
need 'this' for 'str' of type 'string'

}
}
}

I can rationalize what the error means -- the compiler wasn't 
given a string so it requires a concrete object to get the member 
from.  What I don't understand is why *both* of those static ifs 
passed.  If it has the member and I can't get it, and if getting 
the member compiles yet at the same time it doesn't, I'm not sure 
how I can actually make this test work.


It would make sense if the attribute over bar wasn't semantically 
valid, but I can use it in every other way *except* getting the 
string field out of it.


Am I missing something obvious here?