2009-06-27 4 views
5

Ich habe Template-Funktion "vergleichen" wie folgt definiert.Vorlage Instanziierungsfehler

Wenn ich instantiate Vergleich mit String-Literalen der gleichen Länge, der Compiler nicht beschweren. Wenn ich es mit Literalen unterschiedlicher Länge mache, heißt es "error: no matching function für Aufruf zu vergleichen (const char [3], const char [5])"

Ich bin verwirrt, wie Vergleichsfunktion instanziiert werden sollte Zeichenzeiger statt Zeichenarray. Sollen String-Literale nicht immer zu Pointer zerfallen?

Antwort

4

Wie in Gregs Antwort und Kommentare erwähnt, sind die zwei verschiedenen Array-Typen (da das ist, was String-Literale sind) das Problem. Vielleicht möchten Sie die Funktion unverändert für generische Typen belassen, sie aber für Zeichenzeiger und Arrays überladen. Dies ist vor allem dann nützlich, wenn Sie sie etwas anders behandeln möchten.

void compare(char const* a, char const* b) { 
    // do something, possibly use strlen() 
} 

template<int N1, int N2> 
void compare(char const (&a)[N1], char const (&b)[N2]) { 
    // ... 
} 

Wenn Sie Zeichenzeiger explizit angeben möchten nehmen, dass vergleichen sollte, dann werden die Felder automatisch konvertieren:

compare<char const*>("aa", "bbbb"); 

Auf der anderen Seite, vielleicht geschrieben vergleichen konnte mit zwei verschiedenen Arten zu arbeiten ? Dies kann auch für andere Arten nützlich sein, z. vielleicht ruft es f(a) wenn a.size() < b.size(), und f(b) sonst (mit f überlastet). (T1 und T2 sind erlaubt unter den gleichen Typ zu sein, und dies würde ersetzen Ihre Funktion, anstatt sie wie die beiden oben genannten zu überlasten.)

template<typename T1, typename T2> 
void compare(T1 const& a, T2 const& b) { 
    // ... 
} 
6

Ihr Beispiel kompiliert, wenn Sie die Erklärung zu ändern:

void compare(const T* a, const T* b) 

Der Grund dafür ist, dass die Typen der unterschiedlich großen Zeichen-Arrays tatsächlich unterschiedliche Typen sind. Wenn Sie innerhalb der Template-Funktion sizeof(T) verwenden, weiß der Compiler nicht, wie die Mehrdeutigkeit aufgelöst werden soll. Mit der obigen Deklaration rufen Sie eine Template-Funktion mit Pointer-to-T-Typen auf, die der Compiler gerne als const char* bei übergebenen Zeichenfolgen auflöst.

+0

@ Greg, was ist das Problem mit der aktuellen Erklärung? – chappar

+0

Ihre Deklaration wie geschrieben erfordert, dass der Funktionsvergleich zwei Parameter vom gleichen Typ verwendet. "const char [3]" und "const char [5]" sind nicht vom selben Typ. –

+0

In Ihrem vorhandenen Code würde der "Vergleich" zu etwas wie void compare (char a [2], char b [4]) führen. Das Verwenden von Zeigern anstelle von Referenzen bedeutet, dass T sicher als ein "Zeichen" ausgewertet werden kann, anstelle von zwei unterschiedlich großen Arrays (die unterschiedliche Typen sind). – Justicle

3

Der Compiler wird String-Literale lieber als Zeichenpuffer interpretieren, wenn dies möglich ist. Wenn nicht, kann es sie als const char * interpretieren. Allerdings wird der Compiler kein Backtracking durchführen, um die beste Interpretation von T zu finden. Es ist nicht so kompliziert. Sobald entschieden ist, dass T ein const char [3] ist, geht es weiter. Die Auswertung des zweiten Arguments schlägt fehl.

Wenn Sie es nennen mit

compare(static_cast<const char *>("aa"),static_cast<const char *>("bbbb")); 

Sie sind gut zu gehen.

+0

aber es liest wie die Hölle :) – xtofl

+0

vergleichen ("aa", "bbbb"), und Vorlagen + Überladung Auflösung ist nicht annähernd so einfach :( –

+0

Vorlage Überladung Auflösung ist nicht einfach, vereinbart, aber es ist nicht komplex genug, um auf einen Typ für T zu schließen, der beide Variablen hier vereint, obwohl Sie sich eine Implementierung vorstellen könnten, die das würde. –