Search code examples
factorymixinsd

D mixin with factory


Consider I have the following classes:

/// File classes.d
class C {
    string type() { return "C"; };
}

class C1 : C {
    override string type() { return "C1"; };
}

class C2 : C {
    override string type() { return "C1"; };
}

Now I want to implement a factory somewhere else, like:

/// File factory.d
module factory;
import std.functional;
import std.stdio;

void main() {
    mixin(import("classes.d"));
    auto c = cast(typeof(mixin("C1"))) Object.factory("C1");
    writeln(c.type());
}

The compiler (dmd 2.058) says me:

factory.d(7): Error argument C1 to typeof is not an expression

I know the following line compiles well:

auto c = cast(C1) Object.factory("classes.C1");

but this requires me to know the type (C1) at compile time. I want to get the type at runtime (like a string).


Solution

  • mixin(`auto c = cast(typeof(C1)) Object.factory("C1");`)
    

    I don't understand you question, I think: You want to cast dynamically at runtime to a given type? This is not possible in a statically typed language! What you can do is, passing your classes (or whatever) around as void* and using a switch … case to cast it to the needed type (you can also use std.variant, which is maybe the better way, but I've never used it) and then calling different functions (templated functions):

    final switch(which_type) {
        case "C1": foo(cast(C1)bar); break;
        case "C2": foo(cast(C2)bar); break;
    }
    
    void foo(T)(T a) {
    }
    

    You can also generate the switch case at compile-time:

    final switch(which_type) {
        foreach(i; TypeTuple("C1", "C2")) {
            case i: foo(mixin(`cast(` ~ i ~ `)bar`); break;
        }
    }
    

    If you just wanna get the string of the type typeof(bar).stringof will give you the type of bar as string (but this is already known at compile time).