www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template mixin problem with EnumMembers

reply Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= <aferust gmail.com> writes:
The below code works as expected on https://run.dlang.io/, but 
not on my computer. And I don't know why?

I want to access enum members like Options.OUT_FILE_NAME instead 
of Options.StringOption.OUT_FILE_NAME.

Please note that the solutions like "alias something = int;" 
don't work for me. that is not what I need.

In my local computer, pragma(msg, fullname) outputs like:
cast(StringOption)0
cast(StringOption)1
cast(StringOption)2

some error messages I get:
...\options.d-mixin-86(86,11): Error: declaration expected, not )
...\options.d-mixin-86(86,11): Error: no identifier for 
declarator tion

```d
import std.stdio;

class Options{
     public:

     enum StringOption {
         OUT_FILE_NAME,
         RPT_FILE_NAME,
         MAP_FILE_NAME
     }

     import std.traits: EnumMembers;
     mixin template StrOptAliases()
     {
         static foreach(fullname; [EnumMembers!(StringOption)]){
             mixin("alias " ~ fullname.stringof[13..$] ~ " = " ~ 
"Options." ~
                                                    
fullname.stringof ~ ";\n");
             pragma(msg, fullname);
         }
     }

     mixin StrOptAliases;
}

void main()
{
     int opt = Options.OUT_FILE_NAME;
     writeln(opt);
}
```
Oct 02 2021
parent reply Adam Ruppe <destructionator gmail.com> writes:
On Saturday, 2 October 2021 at 22:07:23 UTC, Ferhat Kurtulmuş 
wrote:
 The below code works as expected on https://run.dlang.io/, but 
 not on my computer. And I don't know why?
You used .stringof. That's undefined behavior. Never use stringof. (except for debugging writes) Now, I'd actually probably do this entirely differently... just using opDispatch. ``` class Options{ public: enum StringOption { OUT_FILE_NAME, RPT_FILE_NAME, MAP_FILE_NAME } static template opDispatch(string name) if(__traits(hasMember, StringOption, name)) { alias opDispatch = __traits(getMember, StringOption, name); } } ``` and done. (even that `if` template constraint isn't really necessary and im usally anti-those too, but here it kinda makes sense. in theory. in practice it makes zero difference, but in theory, if the dmd regression that broke these error messages ever actually gets fixed, this would lead to better error messages this way. but anyway moving on) That opDispatch just creates the aliases on-demand. You can't reflect over them directly if you wanted to - you'd still have to check enum members of Options.StringOption, which means things like std.conv.to won't pick it up, but it would work in normal use quite beautifully. If you did want to do the ahead-of-time static foreach way, remember, never use .stringof. Find another way. and tbh i'd ditch the std.traits thing too, it just complicates things. Use the language feature allMembers directly and it simplifies to this: ``` mixin template StrOptAliases() { static foreach(name; __traits(allMembers, StringOption)) mixin("alias " ~ name ~ " = " ~ " __traits(getMember, StringOption, name);"); } ``` Notice that the ONLY thing outside the quotes to the mixin is the name. Everything else is inside. That's often the solution to follow my "never use stringof" advice - just leave things inside the quotes. String interpolation / concat is actually very rarely needed to build mixins. New declaration names are the main exception. But most everything else can just be referenced directly and it leads to code that is both less buggy and easier to read. And, of course, it doesn't rely on random underspecified .stringof behavior that the compiler can change randomly in any release which is just the cherry on top.
Oct 02 2021
parent Ferhat =?UTF-8?B?S3VydHVsbXXFnw==?= <aferust gmail.com> writes:
On Saturday, 2 October 2021 at 22:24:56 UTC, Adam Ruppe wrote:
 On Saturday, 2 October 2021 at 22:07:23 UTC, Ferhat Kurtulmuş 
 wrote:
 [...]
You used .stringof. That's undefined behavior. Never use stringof. (except for debugging writes) [...]
Thank you Adam! I should stop using stringof. Even the docs say it, I ve just seen that https://dlang.org/spec/property.html#stringof. Probably, I will go for your second solution. I appreciate it.
Oct 02 2021