Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
November 21, 2011 mixin on identifier | ||||
---|---|---|---|---|
| ||||
Hi! I'm trying to do: mixin template StateOne() { int value; } class StateSet(T) { mixin T; } int main(string[] argv) { StateSet!StateOne s = new StateSet!StateOne(); return 0; } Compiler complains with: main.d(18): Error: template instance StateSet!(StateOne) StateSet!(StateOne) does not match template declaration StateSet(T) main.d(18): Error: StateSet!(StateOne) is used as a type I think I understand why. And from what I figured I'd need string mixins? But I can't figure out how... Any hints? Johannes |
November 21, 2011 Re: mixin on identifier | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Totz | Make T an alias parameter:
class StateSet(alias T) { … }
David
On 11/22/11 12:38 AM, Johannes Totz wrote:
>
> mixin template StateOne()
> {
> int value;
> }
>
> class StateSet(T)
> {
> mixin T;
> }
>
> int main(string[] argv)
> {
> StateSet!StateOne s = new StateSet!StateOne();
>
> return 0;
> }
|
November 22, 2011 Re: mixin on identifier | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | On 21/11/2011 23:39, David Nadlinger wrote: > Make T an alias parameter: > class StateSet(alias T) { … } > > David Thanks! I was trying to get to something like this: mixin template StateOne() { int value; } mixin template StateTwo() { float data; } class StateSet(alias T ...) { mixin T; } int main(string[] argv) { StateSet!(StateOne, StateTwo) s = new StateSet!(StateOne, StateTwo)(); return 0; } With the docs I got to: template StateSet(alias T, S ...) { class StateSet { mixin T; } } But I have no clue how to expand S into mixin statements. > On 11/22/11 12:38 AM, Johannes Totz wrote: >> >> mixin template StateOne() >> { >> int value; >> } >> >> class StateSet(T) >> { >> mixin T; >> } >> >> int main(string[] argv) >> { >> StateSet!StateOne s = new StateSet!StateOne(); >> >> return 0; >> } > |
November 22, 2011 Re: mixin on identifier | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Totz | Turns out to be surprisingly tricky… A possible solution is:
mixin template StateOne() {
int value;
}
mixin template StateTwo() {
float data;
}
mixin template MixinAll(T...) {
static if (T.length > 0) {
alias T[0] A;
mixin A;
mixin MixinAll!(T[1 .. $]);
}
}
class StateSet(T...){
mixin MixinAll!T;
}
void main() {
auto s = new StateSet!(StateOne, StateTwo)();
}
Hope this helps,
David
On 11/22/11 1:02 AM, Johannes Totz wrote:
> On 21/11/2011 23:39, David Nadlinger wrote:
>> Make T an alias parameter:
>> class StateSet(alias T) { … }
>>
>> David
>
> Thanks!
>
> I was trying to get to something like this:
>
> mixin template StateOne()
> {
> int value;
> }
>
> mixin template StateTwo()
> {
> float data;
> }
>
> class StateSet(alias T ...)
> {
> mixin T;
> }
>
>
> int main(string[] argv)
> {
> StateSet!(StateOne, StateTwo) s = new StateSet!(StateOne, StateTwo)();
>
> return 0;
> }
>
>
> With the docs I got to:
>
> template StateSet(alias T, S ...)
> {
> class StateSet
> {
> mixin T;
> }
> }
>
> But I have no clue how to expand S into mixin statements.
>
>
>
>> On 11/22/11 12:38 AM, Johannes Totz wrote:
>>>
>>> mixin template StateOne()
>>> {
>>> int value;
>>> }
>>>
>>> class StateSet(T)
>>> {
>>> mixin T;
>>> }
>>>
>>> int main(string[] argv)
>>> {
>>> StateSet!StateOne s = new StateSet!StateOne();
>>>
>>> return 0;
>>> }
>>
>
|
November 22, 2011 Re: mixin on identifier | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | On 22/11/2011 04:57, David Nadlinger wrote: > Turns out to be surprisingly tricky… A possible solution is: > > mixin template StateOne() { > int value; > } > > mixin template StateTwo() { > float data; > } > > mixin template MixinAll(T...) { > static if (T.length > 0) { > alias T[0] A; > mixin A; > mixin MixinAll!(T[1 .. $]); > } > } > > class StateSet(T...){ > mixin MixinAll!T; > } > > void main() { > auto s = new StateSet!(StateOne, StateTwo)(); > } > > Hope this helps, > David Thanks a lot, David! A new variant of this (notice the func()s): mixin template StateOne() { int value; void func(int d) { value = d; } } mixin template StateTwo() { float data; void func(float d) { data = d; } } mixin template MixinAll(T...) { static if (T.length > 0) { alias T[0] A; mixin A; mixin MixinAll!(T[1 .. $]); } } class StateSet(T...) { mixin MixinAll!T; } int main(string[] argv) { auto s = new StateSet!(StateOne, StateTwo)(); s.value = 1; s.data = 3.1f; s.func(2); // Error s.func(4.5f); // Ok return 0; } Error: main.StateSet!(StateOne,StateTwo).StateSet.MixinAll!(StateOne,StateTwo).MixinAll!(StateTwo).A!().func at main.d(20) conflicts with main.StateSet!(StateOne,StateTwo).StateSet.MixinAll!(StateOne,StateTwo).A!().func at main.d(10) I suppose I get the error at the first func() call because int is implicitly convertible to float. Is it really? Also, I tried to make the mixed-in members private/etc but this does not seem to have any effect... > On 11/22/11 1:02 AM, Johannes Totz wrote: >> On 21/11/2011 23:39, David Nadlinger wrote: >>> Make T an alias parameter: >>> class StateSet(alias T) { … } >>> >>> David >> >> Thanks! >> >> I was trying to get to something like this: >> >> mixin template StateOne() >> { >> int value; >> } >> >> mixin template StateTwo() >> { >> float data; >> } >> >> class StateSet(alias T ...) >> { >> mixin T; >> } >> >> >> int main(string[] argv) >> { >> StateSet!(StateOne, StateTwo) s = new StateSet!(StateOne, StateTwo)(); >> >> return 0; >> } >> >> >> With the docs I got to: >> >> template StateSet(alias T, S ...) >> { >> class StateSet >> { >> mixin T; >> } >> } >> >> But I have no clue how to expand S into mixin statements. >> >> >> >>> On 11/22/11 12:38 AM, Johannes Totz wrote: >>>> >>>> mixin template StateOne() >>>> { >>>> int value; >>>> } >>>> >>>> class StateSet(T) >>>> { >>>> mixin T; >>>> } >>>> >>>> int main(string[] argv) >>>> { >>>> StateSet!StateOne s = new StateSet!StateOne(); >>>> >>>> return 0; >>>> } >>> >> > |
November 22, 2011 Re: mixin on identifier | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Totz | Hi there, template recursion can get difficult to write sometimes. For the mixin part, since what you're doing is looping on States, another solution is to use string mixins: string stateCode(States...)() { string code; foreach(state; States) code ~= "mixin " ~ __traits(identifier, state) ~ ";\n"; return code; } class StateSet(States...) { mixin(stateCode!(States)); } void main() { auto s = new StateSet!(StateOne, StateTwo)(); s.func(1.5); } the 'stateCode' function produces the code you want inside StateSet and is then mixed in (by a string mixin, not a template mixin). At least to my eyes, the global effect is easier to follow and as a bonus you have access to the entire language to manipulate the strings: slicing, library functions, etc. Hey, now that CT regex are a reality, pretty nifty code manipulation could be done, I guess. Halas, that doesn't change your int/float problem. In the above code, s.func(1) doesn't compile. Strangely, manually inserting the code *does* work: class StateSet(States...) // I don't care for States { int i; void func(int i) { writeln("int: ", i);} float f; void func(float f) { writeln("float: ", f);} } void main() { auto s = new StateSet!(StateOne, StateTwo)(); // or whatever s.func(1); s.func(1.0); } So, maybe it's a compiler bug or mixin templates do not work as I thought they worked. Because, to me, the resulting code inside StateSet should be the same. Workaround: string mixins again: string StateOne() // Note that it's now a function { return q{ int i; void func(int i) { writeln("int: ", i);} }; } string StateTwo() { return q{ float f; void func(float f) { writeln("float: ", f);} }; } string stateCode(States...)() { string code; foreach(state; States) code ~= state ~ ";\n"; return code; } class StateSet(States...) // States will here store function names { mixin( stateCode!States ); } void main() { auto s = new StateSet!(StateOne, StateTwo)(); s.func(1); s.func(1.0); } On the plus side: it works. Disadvantage: you're manipulating strings, so the code 'inside' the strings is not checked... But I get the feeling that tuples should get you what you want. Could you expand a bit more on the usage you envision for StateSet? Philippe |
November 30, 2011 Re: mixin on identifier | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | On 22/11/2011 21:11, Philippe Sigaud wrote: > Hi there, > > template recursion can get difficult to write sometimes. For the mixin > part, since what you're doing is looping on States, another solution > is to use string mixins: > > string stateCode(States...)() > { > string code; > foreach(state; States) > code ~= "mixin " ~ __traits(identifier, state) ~ ";\n"; > return code; > } > > class StateSet(States...) > { > mixin(stateCode!(States)); > } > > void main() > { > auto s = new StateSet!(StateOne, StateTwo)(); > s.func(1.5); > } > > the 'stateCode' function produces the code you want inside StateSet > and is then mixed in (by a string mixin, not a template mixin). > At least to my eyes, the global effect is easier to follow and as a > bonus you have access to the entire language to manipulate the > strings: slicing, library functions, etc. Hey, now that CT regex are a > reality, pretty nifty code manipulation could be done, I guess. > > > Halas, that doesn't change your int/float problem. In the above code, > s.func(1) doesn't compile. > > Strangely, manually inserting the code *does* work: > > class StateSet(States...) // I don't care for States > { > int i; > void func(int i) { writeln("int: ", i);} > float f; > void func(float f) { writeln("float: ", f);} > } > > void main() > { > auto s = new StateSet!(StateOne, StateTwo)(); // or whatever > s.func(1); > s.func(1.0); > } > > So, maybe it's a compiler bug or mixin templates do not work as I > thought they worked. Because, to me, the resulting code inside > StateSet should be the same. > > Workaround: string mixins again: > > string StateOne() // Note that it's now a function > { > return q{ > int i; > void func(int i) { writeln("int: ", i);} > }; > } > > string StateTwo() > { > return q{ > float f; > void func(float f) { writeln("float: ", f);} > }; > } > > string stateCode(States...)() > { > string code; > foreach(state; States) code ~= state ~ ";\n"; > return code; > } > > class StateSet(States...) // States will here store function names > { > mixin( stateCode!States ); > } > > void main() > { > auto s = new StateSet!(StateOne, StateTwo)(); > s.func(1); > s.func(1.0); > } Thanks! > > On the plus side: it works. > Disadvantage: you're manipulating strings, so the code 'inside' the > strings is not checked... > > But I get the feeling that tuples should get you what you want. Could > you expand a bit more on the usage you envision for StateSet? It's a toy project for me to learn D. I'm trying to recreate something I wrote in C++ once. It used extremely messy MPL to have a class inherit individual states from template parameters. But the problem was that func() would not overload from inherited classes. So I tought D's mixins might be suitable. |
November 30, 2011 Re: mixin on identifier | ||||
---|---|---|---|---|
| ||||
Posted in reply to Philippe Sigaud | On 22/11/2011 21:11, Philippe Sigaud wrote: > Hi there, > > template recursion can get difficult to write sometimes. For the mixin > part, since what you're doing is looping on States, another solution > is to use string mixins: > > string stateCode(States...)() > { > string code; > foreach(state; States) > code ~= "mixin " ~ __traits(identifier, state) ~ ";\n"; > return code; > } > > class StateSet(States...) > { > mixin(stateCode!(States)); > } > > void main() > { > auto s = new StateSet!(StateOne, StateTwo)(); > s.func(1.5); > } > > the 'stateCode' function produces the code you want inside StateSet > and is then mixed in (by a string mixin, not a template mixin). > At least to my eyes, the global effect is easier to follow and as a > bonus you have access to the entire language to manipulate the > strings: slicing, library functions, etc. Hey, now that CT regex are a > reality, pretty nifty code manipulation could be done, I guess. > > > Halas, that doesn't change your int/float problem. In the above code, > s.func(1) doesn't compile. > > Strangely, manually inserting the code *does* work: > > class StateSet(States...) // I don't care for States > { > int i; > void func(int i) { writeln("int: ", i);} > float f; > void func(float f) { writeln("float: ", f);} > } > > void main() > { > auto s = new StateSet!(StateOne, StateTwo)(); // or whatever > s.func(1); > s.func(1.0); > } > > So, maybe it's a compiler bug or mixin templates do not work as I > thought they worked. Because, to me, the resulting code inside > StateSet should be the same. Maybe this bug is related: http://d.puremagic.com/issues/show_bug.cgi?id=1182 Looks like the functions are not supposed to overload, would need an explicit alias. > > Workaround: string mixins again: > > string StateOne() // Note that it's now a function > { > return q{ > int i; > void func(int i) { writeln("int: ", i);} > }; > } > > string StateTwo() > { > return q{ > float f; > void func(float f) { writeln("float: ", f);} > }; > } > > string stateCode(States...)() > { > string code; > foreach(state; States) code ~= state ~ ";\n"; > return code; > } > > class StateSet(States...) // States will here store function names > { > mixin( stateCode!States ); > } > > void main() > { > auto s = new StateSet!(StateOne, StateTwo)(); > s.func(1); > s.func(1.0); > } > > On the plus side: it works. > Disadvantage: you're manipulating strings, so the code 'inside' the > strings is not checked... > > But I get the feeling that tuples should get you what you want. Could > you expand a bit more on the usage you envision for StateSet? > > > Philippe |
Copyright © 1999-2021 by the D Language Foundation