First things first (omitting irrelevant portions):
$ dmd --version
DMD64 D Compiler v2.077.0
$ pacman -Qi libphobos
Version : 1:2.077.0-1
Now, getSymbolsByUDA is completely unusable when used in `foreach' loops. First, the symbols it returns seem to be lacking the attribute in question:
// main.d
import std.traits;
enum Attr;
static struct FUBAR
{
@Attr int a;
void dummy()
{
foreach (symbol; getSymbolsByUDA!(FUBAR, Attr))
static assert(hasUDA!(symbol, Attr));
}
}
Tried to compile it with `dmd -c main.d', got this:
src/main.d(11): Error: static assert hasUDA!(symbol, Attr) is false
Commented out the loop and added this:
void main()
{
static assert(hasUDA!(getSymbolsByUDA!(FUBAR, Attr), Attr));
foreach (symbol; getSymbolsByUDA!(FUBAR, Attr))
static assert(hasUDA!(symbol, Attr));
}
And now it makes even less sense:
src/main.d(18): Error: need 'this' for 'a' of type 'int'
src/main.d(19): while evaluating: static assert(hasUDA!(symbol, Attr))
So it has the attribute in `static assert', but doesn't in `foreach'. What's going on?
Comment #1 by kolos80 — 2017-11-08T19:41:49Z
What I meant to say is that it can't even access the symbol to test if it has the attribute. Anyway, here's some more funny (not so at work) stuff:
// main.d
import std.traits;
enum Attr;
static struct FUBAR
{
@Attr int a;
void dummy()
{
static foreach (symbol; getSymbolsByUDA!(FUBAR, Attr))
pragma(msg, getUDAs!(symbol, Attr).stringof);
}
}
void main()
{
static foreach (symbol; getSymbolsByUDA!(FUBAR, Attr))
pragma(msg, getUDAs!(symbol, Attr).stringof);
}
Now I'm lost:
src/main.d(10): Error: value of 'this' is not known at compile time
()
(Attr)
But if I make `dummy' static, it works:
(Attr)
(Attr)
The loop works even on module level (as it should). So it doesn't work only in non-static methods of FUBAR.
Comment #2 by b2.temp — 2017-11-09T03:03:24Z
(In reply to Artem Borisovskiy from comment #1)
> What I meant to say is that it can't even access the symbol to test if it
> has the attribute. Anyway, here's some more funny (not so at work) stuff:
>
> // main.d
> import std.traits;
> enum Attr;
>
> static struct FUBAR
> {
> @Attr int a;
> void dummy()
> {
> static foreach (symbol; getSymbolsByUDA!(FUBAR, Attr))
> pragma(msg, getUDAs!(symbol, Attr).stringof);
> }
> }
>
> void main()
> {
> static foreach (symbol; getSymbolsByUDA!(FUBAR, Attr))
> pragma(msg, getUDAs!(symbol, Attr).stringof);
> }
>
> Now I'm lost:
>
> src/main.d(10): Error: value of 'this' is not known at compile time
> ()
> (Attr)
>
> But if I make `dummy' static, it works:
> (Attr)
> (Attr)
>
> The loop works even on module level (as it should). So it doesn't work only
> in non-static methods of FUBAR.
---
import std.traits;
enum Attr;
struct FUBAR
{
@Attr int a;
void dummy()
{
foreach (i, symbol; getSymbolsByUDA!(FUBAR, Attr))
pragma(msg, getUDAs!(getSymbolsByUDA!(FUBAR, Attr)[i], Attr));
}
void dummy2()
{
static foreach (i; 0..getSymbolsByUDA!(FUBAR, Attr).length)
pragma(msg, getUDAs!(getSymbolsByUDA!(FUBAR, Attr)[i], Attr));
}
}
void main()
{
static foreach (symbol; getSymbolsByUDA!(FUBAR, Attr))
pragma(msg, getUDAs!(symbol, Attr).stringof);
}
---
Good luck.
Comment #3 by kolos80 — 2017-11-09T14:10:37Z
Thanks, but I already found another way of doing it, by using __traits(getMember...). Anyway, both my and your solutions are ugly hacks. They make code even less readable than it was before. It's possible to get rid of some repetition, though:
alias symbols = getSymbolsByUDA!(FUBAR, Attr);
static foreach (i; symbols.length.iota)
pragma(msg, getUDAs!(symbols[i], Attr));
Still, `static foreach (symbol; getSymbolsByUDA!(FUBAR, Attr))' would be nicer.
Comment #4 by robert.schadek — 2024-12-01T16:31:07Z