mixin on identifier
Johannes Totz
johannes at jo-t.de
Wed Nov 30 02:56:32 PST 2011
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.
More information about the Digitalmars-d-learn
mailing list