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

时间:2015-03-02 16:37:05

标签: d mixins template-meta-programming

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

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

2 个答案:

答案 0 :(得分:4)

我希望有人可以提出更清洁的东西,但这个应该做你想做的事情:

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,但它确实要求您的类尚未定义opDispatch。此外,它不能在同一个类中多次使用(您不能在同一范围内从不同的mixin模板重载相同的方法),您必须调用它一次并将所有名称作为args传递。但是,如果您想一次性发送所有名称并且尚未定义opDispatch,那么这可能更为可取。

答案 1 :(得分:2)

你可以使用replace在编译时做一些字符串欺骗来隐藏可怕的连接:

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

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