Mixin's names parameterization with template argument

笑着哭i 提交于 2019-12-12 11:29:02

问题


Is it possible to generate a name for a function within a mixin template? Something like this:

mixin template Generator(string name)
{
    @property void mixin(name) pure nothrow // mixin(name) is not valid :(
    { 
            //some cool stuff here
    }
}

回答1:


I'm hoping somebody can come up with something cleaner, but this should do what you want:

mixin template Generator(string name)
{
    mixin("alias " ~ name ~ " = _fun;");
    @property void _fun pure nothrow
    { 
        //some cool stuff here
    }
}

This unfortunately injects _fun into the local namespace as well, though if you use Generator more than once any calls to _fun will be rejected as ambiguous. This could be a problem if you legitimately have a function named _fun defined elsewhere.

Although you are generating multiple _funs, the calls placed through the aliases created by Generator are not ambiguous as they refer to _fun scoped by a specific template instantiation:

mixin Generator!"foo";
mixin Generator!"bar";

foo();  // not ambiguous, calls Generator!"foo"._fun
bar();  // not ambiguous, calls Generator!"bar"._fun
_fun(); // ambiguous, rejected by compiler

EDIT: Just wanted to throw out another crazy idea I had:

mixin template Generator(names ...) {
  @property void opDispatch(string s)() pure nothrow {
    foreach(name ; names) {
      static if (s == name) {
        // do stuff
      }
    }
  }
}

struct Foo {
  mixin Generator!("hello", "goodbye");
}

void main() {
  Foo foo;

  foo.hello;
  foo.goodbye;
}

This avoids generating a garbage _fun, but it does require that your class doesn't already define opDispatch. Furthermore, it can't be used multiple times in the same class (you can't overload the same method from different mixin templates in the same scope), you have to call it once and pass in all your names as args. This might be preferable, however, if you'd like to send in all the names in one go and don't already define opDispatch.




回答2:


You can use replace to do some string trickery at compile time to hide the horrible concatenations:

mixin(replace(q{ 
    @property void mixin(name) pure nothrow 
    { 
            //some cool stuff here
    }

}, q{mixin(name)}, name));


来源:https://stackoverflow.com/questions/28814898/mixins-names-parameterization-with-template-argument

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!