On Apr 24, 11 09:30, Adam D. Ruppe wrote:
bearophile wrote:
[multiple dispatch and what they use it for.]

I wonder if we could do it in the library by using overloads and
a generated dynamic cast.

class Base {
   // if the types are known, regular overloading does the job
   void multipleDispatchFun(A a, A b) { writeln("Called (A, A)"); }
   void multipleDispatchFun(A a, B b) { writeln("Called (A, B)"); }
   void multipleDispatchFun(B a, B b) { writeln("Called (B, B)"); }
}


This thing is a triple-dispatch. I think these should be static functions?

BTW, you toy example is way too long. 40 lines of template mixin is  enough:

import std.traits, std.typetuple;
template GeneralizeType(T) {
    static if (is(T == class))
        alias Object GeneralizeType;
        //@@@BUG@@@ Should preserve qualifier of T.
    else
        alias T GeneralizeType;
}
mixin template ImplementMultipleDispatch(alias method, alias Parent = __traits(parent, method)) {
    private enum methodName = __traits(identifier, method);
private alias staticMap!(GeneralizeType, ParameterTypeTuple!method) ParamType; //@@@BUG3543@@@ Should take the most common type from all overloads of the // method, but currently it is very complicated due to 3543, so
    //              we just default to use Object.
    alias method opCall;
    static auto opCall(ParamType params) {
        writeln(" ***called the multiple dispatch method");
foreach (overloadedMethod; __traits(getOverloads, Parent, methodName)) {
            //@@@BUG@@@ Should sort overloads by specialization.
            //@@@BUG@@@ Should inherit function attributes from the method
            ParameterTypeTuple!overloadedMethod specializedParam;
            bool matched = true;
            foreach (i, T; ParameterTypeTuple!overloadedMethod) {
                specializedParam[i] = cast(T)params[i];
                static if (is(T == class))
                    if (specializedParam[i] is null) {
//@@@BUG@@@ What if it is not a parameter for dispatch
                        //          but is null? Need to check that.
                        matched = false;
                        break;  // continue label doesn't work.
                    }
            }
            if (matched)
                return overloadedMethod(specializedParam);
        }
throw new Exception("Cannot find suitable overload in " ~ methodName);
    }
}

//------------------------------------------------------------------------------

import std.stdio;

class A : Base {}
class B : Base {}

class Base {
    static private {
        int someFuncImpl(A x, A y, B z, B w, double t) {
            writeln("A, A, B, B, ", t);
            return 3;
        }
        int someFuncImpl(A x, B y, A z, B w, double t) {
            writeln("A, B, A, B, ", t);
            return 2;
        }
        int someFuncImpl(A x, A y, A z, A w, double t) {
            writeln("A, A, A, A, ", t);
            return 1;
        }
    }

    mixin ImplementMultipleDispatch!someFuncImpl someFunc;
}

void main() {
        Base base = new Base();
        Base a = new A();
        Base b = new B();
    A aa = new A();
    B bb = new B();

    assert(1 == Base.someFunc(aa, aa, aa, aa, 0.4));
    assert(3 == Base.someFunc(aa, aa, bb, bb, 0.3));

    assert(1 == Base.someFunc(a, a, a, a, 0.5));
    assert(3 == Base.someFunc(a, a, b, b, 0.6));
    assert(2 == Base.someFunc(a, b, a, b, 0.7));
    Base.someFunc(b, b, b, b, 0.8);  // throws
}

Reply via email to