| |
| Posted by Arafel in reply to cc | PermalinkReply |
|
Arafel
| On 15/6/22 14:26, cc wrote:
> ```d
> import std.traits;
> class XML {}
>
> class Def {
> @XML {
> int x;
> int y;
> }
> int z;
>
> this() {
> static foreach (sym; getSymbolsByUDA!(Def, XML)) {
> }
> }
> }
>
> void main() {
> auto def = new Def;
> }
> ```
> ```
> test.d(12): Error: value of `this` is not known at compile time
> test.d(12): Error: value of `this` is not known at compile time
> ```
>
> Why doesn't this work? There is nothing in the foreach body.
>
> ```d
> alias ALL = getSymbolsByUDA!(Def, XML);
> pragma(msg, ALL.stringof);
> ```
> reports `tuple(this.x, this.y)`. Why is `this.` added?
I think it's a bug either in the `getSymbolsByUDA` implementation, or actually rather in the `__traits` system.
A workaround bypassing `getSymbolsByUDA`:
```d
import std.traits;
import std.meta: Alias;
class XML {}
class Def {
@XML {
int x;
int y;
}
int z;
this() {
static foreach (sym; __traits(allMembers, Def)) {{
alias member = Alias!(__traits(getMember, Def, sym));
static if (hasUDA!(member, XML)) {
pragma(msg, member.stringof);
pragma(msg, sym);
}
}}
}
}
void main() {
auto def = new Def;
}
```
As you can see, it's `getMember` who is returning a reference to the `this` instance. In my view, this is a bug according the documentation and examples [1]. It might be that classes behave differently, but then it should be documented.
In fact, it shouldn't work at all and you'd need to instantiate Def: `getMember` should fail because `x` and `y` are not static.
Interestingly, `hasUDA` (or rather `__traits(getAttributes, ...)`) later doesn't care about the dangling `this` reference, so I'm not sure who is to blame here... in any case, at the very least the documentation doesn't match the actual behavior.
[1]: https://dlang.org/spec/traits.html#getMember
|