2015-03-02 2 views
4

Возможно ли сгенерировать имя для функции в шаблоне mixin? Что-то вроде этого:Имена параметров Mixin с аргументом шаблона

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

Я знаю, что я могу сделать материал с Mixin, но нет подсветки коды для D в строках и отлаживать такой код сложно. –

+1

Возможно, вы захотите попробовать стиль 'q {code here}' string. Они часто выделяются, хотя это не очень помогает при отладке. –

ответ

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 

EDIT: Я просто хотели выбросить другой бредовая идея у меня была:

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 в той же области), вам нужно вызвать его один раз и передать все ваши имена в качестве аргументов. Это может быть предпочтительным, однако, если вы хотите отправить все имена за один раз и еще не определить opDispatch.

+0

Хороший, спасибо. Но я забываю упомянуть, что прецедентом является использование такого «генератора» несколько раз с разными именами. Во всяком случае, ваше решение полезно для других задач =) –

+0

Пожалуйста, отредактируйте соответствующим образом свой вопрос, это слишком актуально ;-) – menjaraz

+1

@DenisGladkiy, 'Generator' можно использовать с несколькими именами, см. Править выше. Я был немного удивлен, что это сработало :) – rcorre

2

Вы можете использовать замену, чтобы сделать некоторые строки фокусов во время компиляции, чтобы скрыть ужасные конкатенации:

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

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