2017-06-19 13 views
2

Anbetracht dieser Code:C++ Funktionsschablone Spezialisierung und Überlastungen

template <class T> 
void f(T p) {   //(1) 
    cout << "Second" << endl; 
} 

template <> 
void f(int *p) {  //(2) 
    cout << "Third" << endl; 
} 


template <class T> 
void f(T* p) {   //(3) 
    cout << "First" << endl; 
} 

Ein Aufruf wie int *p; f(p); ausgeben wird First.

Wenn die Reihenfolge der Erklärungen geändert wird, wie folgt aus:

template <class T> 
void f(T* p) {   //(3) 
    cout << "First" << endl; 
} 


template <class T> 
void f(T p) {   //(1) 
    cout << "Second" << endl; 
} 

template <> 
void f(int *p) {  //(2) 
    cout << "Third" << endl; 
} 

der gleiche Anruf (int *p; f(p);) ausgibt Third.

las ich über die Art und Weise, in der Funktionsschablone Überladungsauflösung Orte nimmt: zuerst die Auflösung nur Nicht-Template-Funktionen betrachtet und die zugrunde liegenden Basisvorlagen. Nachdem die "am meisten spezialisierte" ausgewählt wurde, wird diese Spezialisierung aufgerufen, wenn es eine Template-Funktion ist und eine Spezialisierung für die Parameter hat, die abgeleitet (oder explizit spezifiziert) wurden.

Jetzt ist meine Frage: wie wird entschieden für welche zugrundeliegende Basisvorlage eine Funktion ist eine Spezialisierung? In meinem Beispiel, für welche Funktion Vorlage Überladung ((1) oder (3)) ist (2) eine Spezialisierung?

Meine Vermutung ist, dass wenn eine Spezialisierung deklariert wird, die bereits deklarierten Templates berücksichtigt werden, und von denen die "spezialisierten" (deren Parameter dieser Spezialisierung "am nächsten kommen") ausgewählt werden. Ist das richtig? Könnten Sie mich auch darauf hinweisen, wo dies im Standard angegeben ist?

Antwort

3

Es wird "zuerst" gedruckt, da die Reihenfolge der Deklaration beeinflusst, auf welche Vorlage Sie sich tatsächlich spezialisieren.

Ihr Beispiel hat zwei Funktionsvorlagen, die den gleichen Namen überladen. Im ersten Fall spezialisierst du void f(T p), weil es das einzige Template ist, das bisher gesehen wurde. Im zweiten Fall ist es void f(T* p), das spezialisiert ist. Also ja, deine Vermutung ist richtig. Die Einzelheiten sind in [temp.deduct.decl/1]:

In einer Erklärung, deren declarator-ID bezieht sich auf eine Spezialisierung eines Funktionsschablone, Deduktion Template-Argument wird ausgeführt identifizieren die Spezialisierung auf die der Deklaration bezieht. Dies ist speziell für explizite Instanziierungen, explizite Spezialisierungen, und bestimmte Freund Erklärungen. [...]

Und das beinhaltet die partielle Reihenfolge der Funktionsvorlagen. Die Teilbestellung gilt jedoch nur für die verfügbaren Funktionsschablonendeklarationen zum Zeitpunkt der Einführung Ihrer Spezialisierung.

Und der Standard warnt bei [temp.expl.spec/7]:

Die Platzierung der expliziten Spezialisierung Erklärungen für Funktionsschablonen, [...], kann beeinflussen, ob ein Programm wohlgeformt ist nach der relativen Positionierung der expliziten Spezialisierung Deklarationen und ihre Punkte der Instanziierung in der Übersetzungseinheit wie oben und unten angegeben. Wenn Sie eine Spezialisierung schreiben, seien Sie vorsichtig mit . oder um es kompilieren zu lassen, wird ein solcher Versuch sein, um seine Selbstverbrennung anzuzünden.

+0

Also, von den Template-Funktionen vor der Spezialisierung deklariert, wird die "richtige" mit Teilbestellung gewählt? – user42768

+0

@ user42768 - Nach Vorlage Argumentableitung * und * teilweise Bestellung, ja. – StoryTeller

Verwandte Themen