Interface "indexing"
anonymous via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sun Sep 6 12:44:33 PDT 2015
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)`.
More information about the Digitalmars-d-learn
mailing list