Probleme mit Template-Klasse
-
Hallo,
zur Übung habe ich mir eine kleine Template-Listenklasse geschrieben und um einen Iterator ergänzt (als geschachtelte Klasse innerhalb der Listenklasse). Jetzt wollte ich eine find-Methode implementieren, welche die Liste nach einem Element durchsucht und einen Iterator auf das (erste) gefundene Element zurückgibt.
// liste.h #ifndef liste_h #define liste_h liste_h template<class T> class Liste { //... private: struct Listenelement { //... }; public: // Iteratorklasse class Iterator { public: friend Liste; // ... };// Ende Iteratorklasse void erase(Iterator& pos); // Problem Iterator find(Iterator Start, Iterator Ende, const Listenelement& Wert) const; }; #include "liste.cpp" #endif// liste.cpp template<class T> inline Iterator Liste<T>::find(Iterator Start, Iterator Ende, const Listenelement &Wert) const { //... return Start; }Allerdings macht mir bei dieser Methode der Rückgabetyp "Iterator" Probleme. Der Compiler bringt Fehlermeldungen, die danach aussehen, dass er den Typ Iterator nicht kennt. Allerdings hat er in der Argumentliste mit diesem Typ keine Probleme: wenn ich void zurückgebe (siehe erase()), funktioniert das.
Das Problem liegt irgendwie an der separaten Implementationsdatei. Wenn ich die Implementation direkt im Header-/Templatefile vornehme funktioniert alles. Warum das so ist, verstehe ich allerdings nicht ganz
Vielleicht kann mich jemand aufklären und mir erklären, wie ich das löse, (wenn ich auf einer separaten Implementationsdatei beharre ;)).
-
Nanuq schrieb:
Der Compiler bringt Fehlermeldungen, die danach aussehen, dass er den Typ Iterator nicht kennt.
Ein Tipp für die Zukunft: Schreibe nicht, wonach die Fehlermeldungen für dich "aussehen". Schreibe den exakten Wortlaut der Fehlermeldungen. Wenn's Compilerfehler sind, kennzeichne auch die Position im Code.
Der Unterschied ist nicht, in welcher Datei die Methode definiert ist, sondern ob sie innerhalb der Klassendefinition oder außerhalb steht. Außerhalb musst du Liste<T>::Iterator schreiben, weil Iterator eine innere Klasse von Liste ist.
-
genau genommen muss es
typename Liste<T>::Iterator Liste<T>::findheissen. das typename ist nur dafür da, damit der compiler weiss, dass das nach dem Liste<T>:: ein typ ist, und nicht eine Konstante
-
Danke für die Antworten!
Vielleicht noch zur Ergänzung:
das "typename" ist erforderlich. Wenn ich nur Liste<T>::Iterator schreibe, ist der Compiler trotzdem nicht einverstanden.MFK schrieb:
Ein Tipp für die Zukunft: Schreibe nicht, wonach die Fehlermeldungen für dich "aussehen". Schreibe den exakten Wortlaut der Fehlermeldungen. Wenn's Compilerfehler sind, kennzeichne auch die Position im Code.
Werde ich mir merken. Ich dachte halt, mit "missing ; before Liste<T>::find" fängt man nicht allzuviel an.
-
Kleine Ergänzung: Die Unterklasse 'Listenelement' ist privat, also wird wohl niemand von außen deine find()-Methode aufrufen können (weil niemand außerhalb in der Lage ist, den letzten Parameter bereitzustellen) - verwende dort lieber T oder const T&.
-
Da hast du natürlich Recht, war ein Denkfehler:
Listenelement beinhaltet noch die Pointer auf Vorgänger- und Nachfolger innerhalb der doppelt verketteten Liste, ich suche nur den eigentlichen Wert eines Elements. Entsprechend ist auch der Dereferenzierungoperator des Iterators implementiert.Danke jedenfalls! Ich denke, so sollte das dann passen:
template<class T> inline typename Liste<T>::Iterator Liste<T>::find(Iterator Start, Iterator Ende, const T& Wert) const { while(Start != Ende && *Start != Wert) { Start++; } return Start; }...wobei ich mir vielleicht noch überlegen sollte, was ich zurückgebe, wenn der Wert nicht gefunden wird, anstatt einfach den Iterator auf das Listenende zurückzugeben...?
-
Nanuq schrieb:
...wobei ich mir vielleicht noch überlegen sollte, was ich zurückgebe, wenn der Wert nicht gefunden wird, anstatt einfach den Iterator auf das Listenende zurückzugeben...?
Würd ich aber so machen (tut die STL ja auch) und entsprechend dokumentieren. Dann kannst du immer mit "!= Ende" auf Gültigkeit des Iterators prüfen.
-
Jo, nix anderes erwartet man von einem Iterator in C++.