Multiple alias this, what's the hold up?

Adam D. Ruppe destructionator at gmail.com
Mon Jun 17 13:13:07 UTC 2019


On Sunday, 16 June 2019 at 09:26:21 UTC, Mike Franklin wrote:
> Contrived, naive, very incomplete illustration:
>
>     static foreach(m; __traits(allMembers, typeof(f)))
>     {
>         mixin(
>             ReturnType!(__traits(getMember, typeof(f), 
> m)).stringof
>             ~ " " ~ m ~ "()"
>             ~ "{" ~ __traits(identifier, f) ~ "." ~ m ~ "(); }"
>         );
>     }


It has kinda become my thing to comment on this whenever I can, 
but that code is needlessly hideous.

1) never use .stringof to feed back to the compiler.
2) ensure all newlines inside mixin() are also inside quotes, 
including the one immediately after the (.
3) (almost) never use concatenation to get a member

Following those three rules simplifies that code to:

     static foreach(m; __traits(allMembers, typeof(f)))
     {
         mixin("
             ReturnType!(__traits(getMember, typeof(f), m))
             " ~ m ~ "()
             {__traits(getMember, f, m)(); }"
         );
     }

Notice the only thing concatenated is the name of the function 
now. So much simpler looking code, and it even works across 
module boundaries now.

The reasons behind each rule:

1) stringof breaks if there is another matching name in scope, or 
if the name in question is not in scope at all (imagine a type 
from a user module passed to a different library module)

2) compiler error messages from inside the mixin may have 
misaligned line numbers if this is broken

3) similar pitfalls to #1, including if the symbol is overloaded.

and of course, concat is ugly!


Aside from formatting, you can also go a step further in 
simplification and remove that std.traits entirely with an auto 
function:

     static foreach(m; __traits(allMembers, typeof(f)))
     {
         mixin("
             auto
             " ~ m ~ "()
             { return __traits(getMember, f, m)(); }"
         );
     }

auto functions aren't *exactly* the same... but there's several 
advantages here, including simpler code for return value, 
obviously, but also it will now inherit qualifiers from the 
wrapped function like @nogc, pure, etc., thanks to inference 
rules.


More information about the Digitalmars-d mailing list