mixin on identifier

Philippe Sigaud philippe.sigaud at gmail.com
Tue Nov 22 13:11:10 PST 2011


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


More information about the Digitalmars-d-learn mailing list