Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
April 07, 2017 Using template mixin, with or without mixin ? | ||||
---|---|---|---|---|
| ||||
I want to use mixin to generate function in-place. In template declaration, I can see 'mixin' keyword is optional. Is it true? What is the difference and when I must use one way over another? This is my program: // This works with and without 'mixin' attribute. mixin template funcgen(T, U){ T func1(string pr2){ writeln("Func1: ", pr2); } U func2(string pr3){ writeln("Func2: ", pr3); } } int main(string[] args){ mixin funcgen!(void, void); func1("func1"); func2("func2"); return 0; } |
April 07, 2017 Re: Using template mixin, with or without mixin ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to biocyberman | On 04/07/2017 04:47 PM, biocyberman wrote:
> I want to use mixin to generate function in-place. In template
> declaration, I can see 'mixin' keyword is optional. Is it true? What is
> the difference and when I must use one way over another?
>
> This is my program:
>
> // This works with and without 'mixin' attribute.
> mixin template funcgen(T, U){
>
> T func1(string pr2){
> writeln("Func1: ", pr2);
> }
> U func2(string pr3){
> writeln("Func2: ", pr3);
> }
>
> }
>
> int main(string[] args){
>
> mixin funcgen!(void, void);
> func1("func1");
> func2("func2");
> return 0;
>
> }
The difference is that you can't use funcgen as a regular template:
funcgen!(void, void);
Error: template instance funcgen!(void, void) mixin templates are not regular templates
I think it's good practice to use 'mixin template' if it's intended to be so.
Ali
|
April 08, 2017 Re: Using template mixin, with or without mixin ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Friday, 7 April 2017 at 23:53:12 UTC, Ali Çehreli wrote:
>
> The difference is that you can't use funcgen as a regular template:
>
> funcgen!(void, void);
>
> Error: template instance funcgen!(void, void) mixin templates are not regular templates
>
> I think it's good practice to use 'mixin template' if it's intended to be so.
>
> Ali
Thanks for a very concise answer.
|
April 08, 2017 Re: Using template mixin, with or without mixin ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to biocyberman | On Saturday, 8 April 2017 at 09:47:07 UTC, biocyberman wrote:
> On Friday, 7 April 2017 at 23:53:12 UTC, Ali Çehreli wrote:
>>
>> The difference is that you can't use funcgen as a regular template:
>>
>> funcgen!(void, void);
>>
>> Error: template instance funcgen!(void, void) mixin templates are not regular templates
>>
>> I think it's good practice to use 'mixin template' if it's intended to be so.
>>
>> Ali
>
> Thanks for a very concise answer.
In addition to Ali's answer, mixin templates do their symbol looking at the instantiation site, while regular templates do it at the declaration site. Example:
enum a = 0;
template test1()
{
enum b1 = a; //Okay, a is in scope at the declaration site
//enum c = d1; Error: undefined identifier d1
}
mixin template test2()
{
enum b2 = a; //Okay, a is in scope at the declaration site
enum c = d1; //Okay, d1 is in scope at the *instantiation* site
//enum e = d2; Error: undefined identifier d2
}
void main()
{
enum d1 = 0; //<--d1 is declared here
mixin test1!();
mixin test2!(); //<--so it is in scope here
enum d2 = 0; //d2 was not declared before test2 was mixed in
//so it is not in scope for test2
}
|
April 09, 2017 Re: Using template mixin, with or without mixin ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | On 04/08/2017 11:59 PM, Meta wrote: > enum a = 0; > > template test1() > { > enum b1 = a; //Okay, a is in scope at the declaration site > //enum c = d1; Error: undefined identifier d1 This line works just fine, actually. There's really no difference between a normal template and a mixin template when you use it in a mixin. > } > > mixin template test2() > { > enum b2 = a; //Okay, a is in scope at the declaration site > enum c = d1; //Okay, d1 is in scope at the *instantiation* site > //enum e = d2; Error: undefined identifier d2 > } > > void main() > { > enum d1 = 0; //<--d1 is declared here > mixin test1!(); > mixin test2!(); //<--so it is in scope here > enum d2 = 0; //d2 was not declared before test2 was mixed in > //so it is not in scope for test2 > } |
April 09, 2017 Re: Using template mixin, with or without mixin ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | On Saturday, 8 April 2017 at 22:37:18 UTC, ag0aep6g wrote: > On 04/08/2017 11:59 PM, Meta wrote: >> enum a = 0; >> >> template test1() >> { >> enum b1 = a; //Okay, a is in scope at the declaration site >> //enum c = d1; Error: undefined identifier d1 > > This line works just fine, actually. There's really no difference between a normal template and a mixin template when you use it in a mixin. > >> } >> >> mixin template test2() >> { >> enum b2 = a; //Okay, a is in scope at the declaration site >> enum c = d1; //Okay, d1 is in scope at the *instantiation* site >> //enum e = d2; Error: undefined identifier d2 >> } >> >> void main() >> { >> enum d1 = 0; //<--d1 is declared here >> mixin test1!(); >> mixin test2!(); //<--so it is in scope here >> enum d2 = 0; //d2 was not declared before test2 was mixed in >> //so it is not in scope for test2 >> } Hmm, you're right, but this is not how it is supposed to behave according to the documentation. https://dlang.org/spec/template-mixin.html |
April 09, 2017 Re: Using template mixin, with or without mixin ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Meta | On 04/09/2017 07:44 AM, Meta wrote: > On Saturday, 8 April 2017 at 22:37:18 UTC, ag0aep6g wrote: [...] >> This line works just fine, actually. There's really no difference >> between a normal template and a mixin template when you use it in a >> mixin. [...] > Hmm, you're right, but this is not how it is supposed to behave > according to the documentation. > > https://dlang.org/spec/template-mixin.html The most fitting sentence I can find there is this: "Unlike a template instantiation, a template mixin's body is evaluated within the scope where the mixin appears, not where the template declaration is defined." But that doesn't compare the different kinds of declarations. It compares the invocations: "template instantiation" vs "template mixin". A "template instantiation" is, of course, something like `foo!()`. But the definition of a "template mixin" [1] may be a bit surprising. `mixin bar!()` is a "template mixin". It isn't and doesn't contain a "template instantiation". It's an independent language construct. Also note that the spec says: "The MixinTemplateName refers to a TemplateDeclaration." That is, MixinTemplateName is not restricted to refer to a TemplateMixinDeclaration. Actually, being pedantic, the spec doesn't say that you can use the name of a TemplateMixinDeclaration. Seems to be a minor oversight. PR: https://github.com/dlang/dlang.org/pull/1627 [1] https://dlang.org/spec/template-mixin.html#TemplateMixin |
Copyright © 1999-2021 by the D Language Foundation