digitalmars.D.learn - Trying to understand something about UDAs.
- Kevin Balbas (36/36) Dec 12 2016 I'm trying to figure out how to test whether a UDA struct was
- Adam D. Ruppe (20/29) Dec 12 2016 Easy solution: test the type. @Attr is setting the type as a UDA,
- Kevin Balbas (3/4) Dec 12 2016 That's exactly what I was looking for, thanks. I'm not sure I
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?
Dec 12 2016
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.
Dec 12 2016
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.
Dec 12 2016