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 timeThe 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