Apologies for the long post or stupid questions, I only started to learn D today. I have a use case where various types (A, B, C) need to be associated with instances of different classes (ManagerA, ManagerB, ManagerC). A certain object (globalManager) should redirect operations on those types to their respective managers at compile-time. I intend to use it in the following way:

class GlobalManager(TypeToManagerMapping) {
    public void process(T)(T t) {
        // Must be resolved at compile-time
        TypeToManagerMapping.getManagerForType(T).process(t);
    }
}

// All these types can be completely unrelated, i.e. no base classes
struct A {}
alias ManagerA = DefaultManager!(A)
struct B {}
alias ManagerB = DefaultManager!(B)
struct C {}
alias ManagerC = SomeCustomManager;

// Calls to globalManager should be redirected to these at compile-time
auto mgrA = new ManagerA();
auto mgrB = new ManagerB();
auto mgrC = new ManagerC();

// This is my problem, see below
alias TypeToManagerMapping = ...;

// Pass the mapping as a template parameter so that it can be resolved at compile-time
auto globalManager = new GlobalManager!(TypeToManagerMapping)();

// The following is the module user's code.
// The user may not be aware of mgrA, mgrB, etc, only of globalManager

A a = A();
B b = B();
C c = C();

// Redirection to managers in the following operations
// must be resolved at compile-time

// Should turn into mgrA.process(a), etc
globalManager.process(a);
globalManager.process(b);
globalManager.process(c);

So, I need to map a type (e.g. A) to an instance (e.g. mgrA). I have managed to implement a compile-time map from type to value (by the way, how do I get rid of TValue argument in TypeValuePair? it can be deduced, but I failed to get it working with an eponymous template):

struct TypeValuePair(TKey_, TValue, TValue value_) {
        alias TKey = TKey_;
        static const TValue value = value_;
}

struct StaticMap(THead, Args...) {
        template get(T) {
                static if (Args.length < 0) {
                        static assert(false, "StaticMap does not contain this 
key");
                } else static if (is(T == THead.TKey)) {
                        alias get = THead.value;
                } else {
                        alias get = StaticMap!(Args).get!(T);
                }
        }
}

This works nicely for mapping types to literal values:

alias TypeMap = StaticMap!(
        TypeValuePair!(string, string, "a string"),
        TypeValuePair!(int, string, "an int"),
        TypeValuePair!(bool, string, "a bool")
);
writeln(TypeMap.get!(int));

But fails with "variable cannot be read at compile-time" when I try to pass a class instance in there:

alias TypeMap = StaticMap!(
        TypeValuePair!(A, ManagerA, mgrA)
);
TypeMap.get!(A).process(a);

So, how do I resolve type-to-instance mapping at compile-time so that my user only needs to call globalManager and not know anything about individual managers?

I could easily do this with typeid() calls, but the solution must be purely compile-time (for learning purposes; let's say my code is performance-critical and the lookup would take considerable amount of time).

Reply via email to