Mixin 的名称参数化与模板参数

Mixin's names parameterization with template argument

是否可以在 mixin 模板中为函数生成名称?像这样:

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

我希望有人能想出更干净的东西,但这 应该 做你想做的事:

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

不幸的是,这也将 _fun 注入到本地名称空间中,但如果您多次使用 Generator,任何对 _fun 的调用都将被拒绝为不明确。如果您合法地在别处定义了一个名为 _fun 的函数,这可能是个问题。

虽然您正在生成多个 _funs,但通过 Generator 创建的别名进行的调用并不含糊,因为它们指的是特定模板实例范围内的 _fun

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

编辑:只是想抛出我的另一个疯狂想法:

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;
}

这避免了生成垃圾 _fun,但它确实要求您的 class 尚未定义 opDispatch。此外,它不能在同一个 class 中多次使用(你不能在同一范围内从不同的 mixin 模板重载相同的方法),你必须调用它一次并将你的所有名字作为参数。但是,如果您想一次发送所有名称并且还没有定义 opDispatch.

,这可能更可取

您可以在编译时使用 replace 进行一些字符串欺骗以隐藏可怕的连接:

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

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