Proposal: Didpatching
-
Es existiert bereits ein Proposal für dynamisches Dispatching (n1463). Auch wenn sich dieser nur mit Multimethods beschäftigt hat er doch gewisse Ähnlichkeiten mit diesem. Ich halte n1463 nicht für sonderlich gelungen. Deswegen würde ich gerne eine alternative Vorschlagen. Vorher würde ich allerdigs gerne wissen, was ihr davon haltet und wie man ihn möglicherweise noch verbessern könnte.
Normalerweise haben Funktionsargumente einen statischen Typ:
void foo (Typ & x) {...}
Das dispatchen des Typs ist eine umständliche und unübersichtliche Angelegenheit. Man müsste mit dnymaic_casts herumhantieren.
Deswegen schlage ich eine Möglichkeit vor, neben dem statischen (damit meine ich den zur compilezeit bekannten) Typ auch den dynamischen (also zur Laufzeit tatsächlich vorliegenden) Typ angeben zu können. Da nur Zeiger und Referenzen Zur Laufzeit auf Objekte eines anderen Typs verweisen können macht auch nur hier diese Angabe sinn. Das ganze sieht so aus:
void foo (Basis & x) {...} // eine Art Fallback void foo (Basis & Derivat1 x) {...} void foo (Basis & Derivat2 x) {...} void foo (Basis & Derivat3 x) {...} ...
Die erste Zeile ist eine klassische Funktionsdefinition und dient gleichzeitig als Fallback, falls keine passende dynamische Überladung gefunden wird. Zur Laufzeit wird entschieden, welche denn die am besten pasende ist. Es wird immer die am weitesten spezialisierte Variante bevorzugt.
Unklar ist noch folgendes: Was passiert, wenn es es Mehrdeutigkeiten geben sollte? Soll die Fallback-Variante aufgerufen werden oder sollte eine Exception fliegen?Der Rückgabetyp der dynamisch überladenen Versionen könnte kovariant gegenüber der Fallback-Variante sein.
Basis & foo (Basis & x); Derivat1 & foo (Basis & Derivat1 x);
Das klassischte aller Beispiel für eine Anwendung sähe so aus:
struct Shape {...}; struct Square : Shape {...}; struct Triangle : Shape {...}; bool overlap (Shape & a, Shape & b) {...} bool overlap (Shape & Square a, Shape & Triangle b) {...} bool overlap (Shape & Triangle a, Shape & Square b) {...}
Ungeklärt ist ob es immer die Fallbackvariante geben muss. Ich denke nicht.
Außerdem müsste noch geklrät werden, ob folgendes erlaubt ist:
void foo (Basis & x) {...} template<typename T> void foo (Basis & T x) {...}
Ich sehe keinen Sinn darin.
--- Soviel zumersten Teil des Vorschlags. ---
Wenn man schon zur Laufzeit auswählt, welche Variante aufgerufen wird, kann man auch gleich noch einen Schritt weiter in Richtung Patternmatching gehen.
Statt einen Typ anzugeben könnte man auch ein Objekt angeben. Hier würde es auch sinn machen, wenn es sich nicht um eine Referenz oder einen Zeiger handelt. Damit es nicht zu Mehrdeutigkeiten kommt stellt man der Variable ein @ voran.
enum State {running, stopped}; void foo (State @running) {...} void foo (State @stopped) {...}
Das köntne zu deutlich übersichtlicherem Code führen und lässt sich viel leichter erweitern.
Auch heir kann man selbstverständlich wie üblich eine Fallbackvariante implementieren.Um Patternmatching in einer Form zu erlauben, wie man es in ML oder anderen funktionalen Sprachen findet müsste man viel weitreichendere Erweiterungen der Sprache hinzufügen. Es würde wohl schwer seine passende Synthax zu finden, mittels der man gestatten kann Objekte zu dekonstruieren.
-
ginge nicht statt
void foo(Base & Concrete x);
ein
void foo(Dispatch<Base,Concrete>& x);
oder
void foo(Concrete<Base> & x);
?
Devil
-
n, das wäre ja wieder statisch
Unklar ist noch folgendes: Was passiert, wenn es es Mehrdeutigkeiten geben sollte? Soll die Fallback-Variante aufgerufen werden oder sollte eine Exception fliegen?
mehrdeutigkeiten können schon zur compilezeit aufgedeckt werden,sowas darf nicht passieren, da nicht auflösbar:
class derived:public base1,public base2{ }; void foo{base1&derived); void foo(base2&derived);//bumm //das muss schon zur compilezeit verhindert werden!
template<typename T>
void foo (Basis & T x) {...}void foo(basis x){...} würde doch demselben entsprechen
enum State {running, stopped}; void foo (State @running) {...} void foo (State @stopped) {...}
ich seh da persönlich nich soviel sinn drin...(ausserdem is das @ eine so schwer erreichbare taste für den ottonormal programmierer :D)