Wie funktioniert die Auflösung partieller Spezialisierungen?
-
Wie funktioniert die Auflösung partieller Spezialisierungen?
-
Also ich schreibe z.B.:
#include <iostream> template < typename targetType, class sourceType > inline bool is_of_type( sourceType arg1 ) { return dynamic_cast < targetType > ( arg1 ) != 0; } class A { public: A( void ) { } virtual ~A( void ) { } }; class B : public A { public: B( void ) { } virtual ~B( void ) { } }; int main( int argc, char** argv ) { using std::cout; using std::endl; A* a = new A(); B* b = new B(); if ( is_of_type < A* > ( b ) ) { cout << "b is of type A*" << endl; } else { cout << "b isn't of type A*" << endl; } if ( is_of_type < B* > ( a ) ) { cout << "a is of type B*" << endl; } else { cout << "a isn't of type B*" << endl; } delete b; delete a; return 0; }Warum muss ich den zweiten Template-Parameter nicht angeben? Wie findet der Compiler die passende Funktion?
-
Na überleg mal...
Der Typ der Variable, die du übergibst ist dem Compiler bekannt. Daher kann der Compiler dementsprechen auch das Funktionstemplate ausprägen.

-
Mich würde die Reihenfolge der Suche interessieren, oder die Regeln, die ein ISO C++ Compiler dabei anwendet. Gibt es dafür irgendwo eine Zusammenfassung?
-
Du könntest das im Final Draft vom Standard nachlesen. Der ist frei zugänglich sollte hier eigentlich irgendwo verlinkt sein...
Die Regeln sind allerdings nicht ganz einfach, gerade bei partiellen Spezialisierungen.
-
Hallo,
Gibt es dafür irgendwo eine Zusammenfassung?
Hier mal eine grobe Übersicht:
zuerst wird geschaut ob es überhaupt ein passendes Primary-Template gibt. Falls dem so ist, wird danach geschaut, ob dieses Template spezialisiert wurde. Falls ja, so wird geschaut welche Spezialisierungen prinzipiell auf die Argumente passen.
Falls hier mehr als eine Spezialisierung übrig bleibt wird nun geprüft, welche
davon die speziellste ist (bzw. ob es eine eindeutig speziellste gibt).
Dazu werden die "partial ordering rules" für Funktionstemplates verwendet.Also in etwa:
1. Prüfe ob ein primary-Template existiert.
2. Falls ja, suche alle passenden Spezialisierungen
3. Falls es mehr als eine Spezialisierung gibt, bestimmte die speziellste
Dazu:
a) Erzeuge für jede Spezialisierungen eine Funktion die die gleiche Template-Parameterliste hat sowie einen Funktionsparameter der vom Typ der Spezialisierung ist.
b) führe partial ordering der zuvor erstellten Funktionen durch:
Dazu:
i. Ersetze die Template-Parameter jeder Funktion durch eindeutige Dummy-Typen und schreibe diese in eine Liste (eine für jede Funktion).
ii. Matche jede Funktion gegen die Liste jeder anderen Funktion.Der Matching-Prozess betrachtet dabei immer nacheinander zwei Funktionen f1, f2 und die passenden Liste l1 und l2. Sollte f1 auf l2 passen nicht aber f2 auf l2, dann ist f2 spezieller als f1 und andersherum.
Andernfalls ist keine Funktion spezieller als die andere und der Prozess schlägt mit einem Mehrdeutigkeitsfehler fehl.Angenommen wir haben folgendes Beispiel:
// primary-template template <class T> struct Foo {}; // 1. // Spezialisierung für Pointer template <class T> struct Foo<T*> {}; // 2. // Spezialisierung für Funktionszeiger mit einem Parameter template <class R, class P> struct Foo<R (*)(P)>; // 3.Und die Instanziierung:
Foo <void (*)(int)> p;1. Prüfe ob ein primary-Template existiert: Jupp. Foo<T> kann mit void ()(int)
instanziiert werden.
2. Falls ja, suche alle passenden Spezialisierungen: Ok. Foo<T> und Foo<R(*)(P)>3. Falls es mehr als eine Spezialisierung gibt: gibt es.
a) Erzeuge für jede Spezialisierungen eine Funktion die die gleiche Template-Parameterliste hat sowie einen Funktionsparameter der vom Typ der Spezialisierung ist.
template <class T> void foo( Foo<T*> ); template <class R, class P> void foo( Foo<R (*)(P)> );i. Ersetze die Template-Parameter jeder Funktion durch eindeutige Dummy-Typen:
Spezialisierung 1: (A1*)
Spezialisierung 2: (A2 (*)(A3))ii. Matche jede Funktion gegen die Liste jeder anderen Funktion.
Matche 1 gegen 2: Also T* gegen (A2 (*)(A3)): geht wir müssen einfach nur T durch A2(A3) ersetzen.
Matche 2 gegen 1: Also R, P gegen (A1*): geht nicht. Wir haben zwei Parameter aber nur ein Argument.
Ergebnis: Spezialisierung 1 passt auf die Argumenten von Spezialisierung 2. Die Argumente von Spezialisierung 1 aber nicht auf Spezialisierung 2. Damit ist Spezialisierung 2 spezieller als Spezialisierung 1.
Es wird am Ende also Spezialsierung 2 ausgewählt.
-
Danke für die ausführliche Antwort!