On Sunday 06 September 2015 19:32, Prudence wrote: > Any ideas?
As far as I understand (which may not be very far), you'd like to avoid keeping a list of the types that's separate from the type declarations themselves. Let's start with some code where the list is manually kept in sync with the types: ---- import std.stdio; import std.typetuple; interface I {void go();} class A : I {void go() {writeln("'Allo 'Allo!");}} class B : I {void go() {writeln("Bonjourno!");}} class C : I {void go() {writeln("Cha cha ciao!");}} alias Types = TypeTuple!(A, B, C); /* You'd like to avoid this, right? */ I create(uint index) { switch(index) { /* Note how the switch cases are generated with (static) foreach: */ foreach(i, T; Types) case i: return new T; default: throw new Exception(""); } } void main() { auto a = create(0); a.go(); /* 'Allo 'Allo! */ auto b = create(1); b.go(); /* Bonjourno! */ auto c = create(2); c.go(); /* Cha cha ciao! */ auto d = create(3); /* throws exception */ } ---- To avoid having to touch two places when you add a class, you can use a somewhat obscure feature of D, the NewAnonClassExpression: ---- alias Types = TypeTuple!( typeof(new class () I {void go() {writeln("'Allo 'Allo!");}}), typeof(new class () I {void go() {writeln("Bonjourno!");}}), typeof(new class () I {void go() {writeln("Cha cha ciao!");}}), ); ---- The syntax is described here: http://dlang.org/class.html#anonymous Another alternative is to generate `Types` by getting all members of the module and filtering out everything that doesn't implement I: ---- class A : I {void go() {writeln("'Allo 'Allo!");}} class B : I {void go() {writeln("Bonjourno!");}} class C : I {void go() {writeln("Cha cha ciao!");}} template IfImplementsI(string thing_s) { alias thing = TypeTuple!(__traits(getMember, module_, thing_s)); static if (is(thing[0] : I) && !is(thing[0] == I)) alias IfImplementsI = thing; else alias IfImplementsI = TypeTuple!(); } alias module_ = TypeTuple!(__traits(parent, {})); alias Types = staticMap!(IfImplementsI, __traits(allMembers, module_)); ---- That can probably be done more elegantly. I'm sure one could also generate an enum with nice names along with that, so that it's not `create(0)` but `create(MyEnum.A)`.