Compile-type array of classes?

Tobias Pankrath tobias at pankrath.net
Sun Feb 23 14:23:23 PST 2014


On Sunday, 23 February 2014 at 22:14:17 UTC, Gordon wrote:
> On Sunday, 23 February 2014 at 20:52:58 UTC, anonymous wrote:
>> On Sunday, 23 February 2014 at 20:34:07 UTC, Gordon wrote:
>>>
>>> Given one interface, and multiple implementation classes, I 
>>> want to create a list of the classes (in compile time).
>>
>> import std.typetuple: TypeTuple;
>> alias available_animals = TypeTuple!(Dog, Cat);
>
> First, Thanks!
> D is amazing :)
>
> Now, this lead me to a weird error.
> This is the complete (contrived) program:
> ===
> import std.stdio,
> 	std.string,
> 	std.typetuple;
>
> interface Animal
> {
>   static const string name() @property;
>   void make_noise();
> }
>
> class Dog : Animal
> {
>    static const string name() @property { return "dog" ; }
>    void make_noise() { writeln("woof"); }
> }
>
> class Cat : Animal
> {
>    static const string name() @property { return "cat" ; }
>    void make_noise() { writeln("meow"); }
> }
>
> alias available_animals = TypeTuple!(Dog, Cat);
>
> void main()
> {
> 	string input_from_user = "dog";
> 	Animal a;
> 	foreach (i; available_animals) {
> 		if (i.name == input_from_user)
> 			a = new i;
> 	}
>
>         //// -- This doesn't compile ---
> 	//// writeln("The ", a.name, " makes: ");
>         ////
>
> 	a.make_noise();
> }
> ===
>
> Running the program without the marked "writeln" works fine, as 
> expected.
>
> Compiling with the marked writeln, produces an "underfined 
> reference" error:
> ====
> $ rdmd animals.d
> /tmp/.rdmd-34574/rdmd-animals.d-796CFD5A46BFE9DF13BF873F65EA656C/objs/animals.o: 
> In function `_Dmain':
> animals.d:(.text._Dmain+0xdf): undefined reference to 
> `_D7animals6Animal4nameFNdZAya'
> collect2: error: ld returned 1 exit status
> --- errorlevel 1
> ====
>
> BTW - a work-around is simple, my question is about the theory 
> behind this.
>
> I understand that "Animal::name" is undefined (since "Animal" 
> is an interface).
>
> but if during runtime "a" has an actual type, why does the 
> compiler looks for "Animal::name" instead of Dog::Name or 
> Cat::Name (based on the type of "a") ?

static methods are statically dispatched. Since they can called 
without an instance, they cannot be dispatched dynamically in 
general.

> It is likely because of the "static", but if I remove the 
> "static" than the 'foreach' loop won't compile, because "name" 
> is not static.
Correct.

> So this seems like some impossible situation...
A non static method that forwards to the static one or comparison 
of the user input to the class names come to mind. Or use some 
instance of i to call (the non-static) method name.


More information about the Digitalmars-d-learn mailing list