2009-06-27 12 views
5

Mam funkcję szablonu "porównaj" zdefiniowaną poniżej.Błąd instancji szablonu

#include<iostream> 
using namespace std; 

template<typename T> 
void compare(const T&a, const T& b) 
{ 
    cout<<"Inside compare"<<endl; 
} 

main() 
{ 
compare("aa","bb"); 
compare("aa","bbbb"); 
} 

Kiedy używam instancji porównawczej z literałami ciągów o tej samej długości, kompilator nie narzeka. Kiedy robię to z literałami o różnej długości, mówi "błąd: brak funkcji dopasowującej dla połączenia do porównania (const char [3], const char [5])"

Jestem zdezorientowany, ponieważ funkcja porównywania powinna być tworzona z wskaźnik znaku zamiast tablicy znaków . Czy ciągi literałów nie powinny zawsze zanikać do wskaźnika?

Odpowiedz

4

Jak stwierdzono w odpowiedziach Grega i komentarzach, dwa różne typy tablic (ponieważ to są literały ciągów znaków) stanowią problem. Możesz opuścić funkcję tak jak jest dla typów ogólnych, ale przeciąż ją dla wskaźników i tablic znaków, jest to przydatne zwłaszcza wtedy, gdy chcesz traktować je nieco inaczej.

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]) { 
    // ... 
} 

Jeśli chcesz określić, że porównanie powinno wskazówek charakter jawnie, to macierze automatycznie przeliczy:

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

Z drugiej strony, może porównać można zapisać do pracy z dwoma różnymi rodzajami ? Może to być przydatne również dla innych typów, np. może to wywołuje f(a), jeśli w inny sposób (przy przeciążeniu f). (T1 i T2 mogą być tego samego typu poniżej, a to byłoby zastąpić funkcję zamiast przeciążania go jak powyżej dwóch.)

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

Twój przykład kompiluje jeśli zmienisz oświadczenie:

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

Powodem jest to, że typy różnych wielkości tablic znakowych są rzeczywiście różne typy. Jeśli używałbyś sizeof(T) w funkcji szablonu, kompilator nie wiedziałby, jak rozwiązać niejednoznaczność. Z powyższą deklaracją wywołujesz funkcję szablonu z typami wskaźnikowymi, które kompilator z przyjemnością rozwiąże jako const char* podczas przekazywania ciągów znaków.

+0

@Greg, na czym polega problem z bieżącym deklaracji? – chappar

+0

Twoja deklaracja w formie pisemnej wymaga, aby porównanie funkcji miało dwa parametry dokładnie tego samego typu. "const char [3]" i "const char [5]" nie są tego samego typu. –

+0

W twoim istniejącym kodzie, "porównywanie" będzie porównywane z czymś podobnym do void compare (char a [2], char b [4]). Używanie wskaźników zamiast odwołań oznacza, że ​​T można bezpiecznie ocenić jako "znak", zamiast dwóch macierzy o różnych rozmiarach (które są różnymi typami). – Justicle

3

Kompilator woli interpretować ciągi znaków jako bufory znaków, jeśli może. Jeśli nie, może zinterpretować je jako const char *. Jednak kompilator nie wykona żadnego cofania, aby spróbować znaleźć najlepszą interpretację T. To nie jest takie skomplikowane. Gdy zdecyduje, że T jest const char [3], porusza się dalej. Ocena drugiego argumentu kończy się niepowodzeniem.

Jeśli zadzwonisz go

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

jesteś dobry, aby przejść.

+0

ale czyta się jak cholera :) – xtofl

+0

porównaj ("aa", "bbbb"), a szablony + rozdzielczość przeciążania nie jest prawie taka prosta :( –

+0

Rozładowanie szablonu nie jest proste, uzgodnione, ale nie jest wystarczająco złożony, aby wywnioskować typ dla T, który ujednolica obie zmienne tutaj, nawet jeśli można sobie wyobrazić taką implementację. –

Powiązane problemy