digitalmars.D.learn - Using getSymbolsByUDA in a static foreach loop
- Jack Stouffer (40/40) Jan 19 2022 I'm trying to use getSymbolsByUDA in order to loop over all of
- Adam D Ruppe (9/15) Jan 19 2022 The getSymbols returns aliases, meaning you hit what I wrote
- Jack Stouffer (7/9) Jan 19 2022 The error is actually coming from trying to use the result of
- Adam D Ruppe (6/8) Jan 19 2022 huh......
- Jack Stouffer (41/44) Jan 19 2022 Unless I'm missing something obvious this has to be a DMD bug,
- Adam Ruppe (5/7) Jan 19 2022 member here is a string, not the member. I prefer to call it
- Jack Stouffer (39/47) Jan 19 2022 Thanks, that fixed it. Final working version for anyone who finds
I'm trying to use getSymbolsByUDA in order to loop over all of
the members in a struct with a certain UDA, and then call a
function on the member. The plan is to use this to avoid looping
over an array of function pointers.
However, the compiler is giving a strange error and the
documentation of getSymbolsByUDA is unhelpful, as there are no
practical use-case examples.
Here's a very simplified version of my code
```d
import std.traits;
enum Runnable;
struct SubSystem
{
void run();
}
struct Manager
{
Runnable SubSystem subsystem;
void run()
{
static foreach(system; getSymbolsByUDA!(Manager,
Runnable))
{
system.run();
}
}
}
void main()
{
Manager m;
m.run();
}
```
Result:
```
onlineapp.d(16): Error: value of `this` is not known at compile
time
```
This seems to me to be the logical way to write this code. What
am I missing?
Jan 19 2022
On Wednesday, 19 January 2022 at 20:46:17 UTC, Jack Stouffer
wrote:
static foreach(system; getSymbolsByUDA!(Manager,
Runnable))
{
system.run();
onlineapp.d(16): Error: value of `this` is not known at compile
time
The getSymbols returns aliases, meaning you hit what I wrote
about a few days ago:
http://dpldocs.info/this-week-in-d/Blog.Posted_2022_01_10.html#tip-of-the-week
The `this` is a runtime value and all the other `static` things
work on compile time info.
So you want to `__traits(child, system, this).run()` and it
should work - the traits child will re-attach a this value.
Jan 19 2022
On Wednesday, 19 January 2022 at 20:53:29 UTC, Adam D Ruppe wrote:So you want to `__traits(child, system, this).run()` and it should work - the traits child will re-attach a this value.The error is actually coming from trying to use the result of getSymbolsByUDA in the right part of the `static foreach`, not the call to the `run` function. Which was odd to me because I thought it just returned a `AliasSeq`. Here's a link to the erroring code with your traits change: https://run.dlang.io/is/gO84ox
Jan 19 2022
On Wednesday, 19 January 2022 at 21:44:57 UTC, Jack Stouffer wrote:The error is actually coming from trying to use the result of getSymbolsByUDA in the right part of the `static foreach`huh...... I never use most of std.traits, they just complicate things. Bleh idk, I wouldn't bother with it and loop through the __traits instead.
Jan 19 2022
On Wednesday, 19 January 2022 at 21:49:12 UTC, Adam D Ruppe wrote:I never use most of std.traits, they just complicate things. Bleh idk, I wouldn't bother with it and loop through the __traits instead.Unless I'm missing something obvious this has to be a DMD bug, because this prints nothing: ```d import std.traits; import std.stdio; enum Runnable; struct SubSystem { void run() { writeln("SubSystem ran"); } } struct Manager { Runnable SubSystem subsystem; void run() { static foreach(member; __traits(allMembers, Manager)) { static foreach (attribute; __traits(getAttributes, member)) { static if (attribute == Runnable) { __traits(child, Manager, member).run(); } } } } } void main() { Manager m; m.run(); } ``` The `__traits(getAttributes, member)` call always returns an empty tuple. Calling `__traits(getAttributes, Manager.subsystem)` manually works as expected.
Jan 19 2022
On Thursday, 20 January 2022 at 00:55:33 UTC, Jack Stouffer wrote:
static foreach(member; __traits(allMembers,
Manager))
member here is a string, not the member. I prefer to call it
memberName.
Then you __traits(getMember, Manager, memberName) to actually get
the alias you can pass to getAttributes.
Jan 19 2022
On Thursday, 20 January 2022 at 01:14:51 UTC, Adam Ruppe wrote:On Thursday, 20 January 2022 at 00:55:33 UTC, Jack Stouffer wrote:Thanks, that fixed it. Final working version for anyone who finds this thread: ```d import std.traits; import std.stdio; enum Runnable; struct SubSystem { void run() { writeln("SubSystem ran"); } } struct Manager { Runnable SubSystem subsystem; void run() { static foreach(memberName; __traits(allMembers, Manager)) { static foreach (attribute; __traits(getAttributes, __traits(getMember, Manager, memberName))) { static if (is(attribute == Runnable)) { __traits(getMember, Manager, memberName).run(); } } } } } void main() { Manager m; m.run(); } ```static foreach(member; __traits(allMembers, Manager))member here is a string, not the member. I prefer to call it memberName. Then you __traits(getMember, Manager, memberName) to actually get the alias you can pass to getAttributes.
Jan 19 2022








Jack Stouffer <jack jackstouffer.com>