www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - static foreach and function generation

reply Jean-Louis Leroy <jl leroy.nyc> writes:
Consider:

module genfun;

   import std.stdio, std.format, std.traits;

   void foo(int a) { writeln("foo(%s)".format(a)); }
   void foo(int a, int b) { writeln("foo(%s, %s)".format(a, b)); }

   static foreach (fun; __traits(allMembers, genfun)) {
     static if (fun == "foo") {
       static if (is(typeof(__traits(getOverloads, genfun, fun)))) 
{
         static foreach (ovl; __traits(getOverloads, genfun, fun)) 
{
           void foobar(Parameters!ovl args) { // HERE
             write("calling ");
             foo(args); // HERE
           }
         }
       }
     }
   }

   void main()
   {
     foobar(1); // calling foo(1)
     foobar(1, 2); // calling foo(1, 2)
   }

Now I would like to change `foo` and `foobar` to calculated 
symbols where marked. I would also like to use as little string 
mixin as possible. I tried:

   static foreach (fun; __traits(allMembers, genfun)) {
     static if (fun == "foo") {
       static if (is(typeof(__traits(getOverloads, genfun, fun)))) 
{
         static foreach (ovl; __traits(getOverloads, genfun, fun)) 
{
           void mixin(fun + "bar")(Parameters!ovl args) { // 1
             write("calling ");
             mixin(fun)(args); // 2
           }
         }
       }
     }
   }



This works:

   static foreach (fun; __traits(allMembers, genfun)) {
     static if (fun == "foo") {
       static if (is(typeof(__traits(getOverloads, genfun, fun)))) 
{
         static foreach (ovl; __traits(getOverloads, genfun, fun)) 
{
           void internal(Parameters!ovl args) {
             mixin(fun)(args);
           }
           mixin("alias %sbar = internal;".format(fun));
         }
       }
     }
   }


Does anyone see a potential problems with this? Or a better 
solution? I would like to avoid the alias.
Jul 23 2018
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 23.07.2018 19:05, Jean-Louis Leroy wrote:
 
 
 This works:
 
    static foreach (fun; __traits(allMembers, genfun)) {
      static if (fun == "foo") {
        static if (is(typeof(__traits(getOverloads, genfun, fun)))) {
          static foreach (ovl; __traits(getOverloads, genfun, fun)) {
            void internal(Parameters!ovl args) {
              mixin(fun)(args);
            }
            mixin("alias %sbar = internal;".format(fun));
          }
        }
      }
    }
 
 
 Does anyone see a potential problems with this?
It generates additional symbols.
 Or a better solution? I 
 would like to avoid the alias.
You can mix in the entire declaration. mixin(`void `~fun~`bar(Parameters!ovl args) { mixin(fun)(args); }`); It would of course be useful if the locations where string mixins can occur were less restricted, such that things like void mixin(fun~`bar`)(Parameters!ovl args){ ... } would work too, but this will require a DIP.
Jul 23 2018