Template-Klassen-Vererbungs-Fehler
-
Moin,
das ist wahrscheinlich der komplizierteste Beitrag im ganzen Forum...

Also ich habe folgenden Code:
#include <list> template <class T_TYPE> class A { class A_Entry { //... }; std::list<A_Entry*> my_list; //std::list<A_Entry*>::iterator my_list_itr; };Geht soweit. Wenn ich nun das Kommentarzeichen wegnehme, kommt der Error:
derived.cpp:28: error: type ‘std::list<A<T_TYPE>::A_Entry*, std::allocator<A<T_TYPE>::A_Entry*> >’ is not derived from type ‘A<T_TYPE>’(gcc version 4.2.1 (SUSE Linux))
Ich verstehe den Error überhaupt nicht. Nehme ich die Zeile "template <class T_TYPE>" heraus (also so, dass die Klasse keine Template-Klasse mehr ist), geht alles wunderbar. Liegt also an dem Template. Aber wieso kann ich eine Liste, aber keinen zugehörigen Iterator deklarieren?
Vielen Dank für Eure Hilfe im Voraus!
voidpointer
-
voidpointer schrieb:
das ist wahrscheinlich der komplizierteste Beitrag im ganzen Forum...

Nein. Eigentlich trivial.
voidpointer schrieb:
Ich verstehe den Error überhaupt nicht. Nehme ich die Zeile "template <class T_TYPE>" heraus (also so, dass die Klasse keine Template-Klasse mehr ist), geht alles wunderbar. Liegt also an dem Template. Aber wieso kann ich eine Liste, aber keinen zugehörigen Iterator deklarieren?
Ganz einfach: Woher soll der Compiler wissen, was er da für einen Typ vor sich hat?
iteratorkönnte genauso gut eine Membervariable sein. Darum brauchst du das Schlüsselworttypename.#include <list> template <class T_TYPE> class A { class A_Entry { //... }; std::list<A_Entry*> my_list; typename std::list<A_Entry*>::iterator my_list_itr; };
-
Tut mir leid, verstehe das nicht ganz oO
Kenne das Wort typename eigtl. nur von Templates:
template<typename T> func() ...
Hat das dann hier eine neue Bedeutung?
Und: warum könnte iterator auch eine Membervariable sein? Ist das Problem, dass der Iterator wissen muss, worauf er zeigt, während das die Liste nicht wissen brauch? Im Grunde genommen ist es für die Liste doch auch relevant, oder nicht?
-
::iterator könnte auch eine statische variable von list sein... damit der compiler weis dass es sich um einen typ handelt muss man typename mit angeben...
-
voidpointer schrieb:
Tut mir leid, verstehe das nicht ganz oO
Kenne das Wort typename eigtl. nur von Templates:
template<typename T> func() ...
Hat das dann hier eine neue Bedeutung?
Und: warum könnte iterator auch eine Membervariable sein? Ist das Problem, dass der Iterator wissen muss, worauf er zeigt, während das die Liste nicht wissen brauch? Im Grunde genommen ist es für die Liste doch auch relevant, oder nicht?
Das hat direkt nichts damit zu tun.
std::list<A_Entry*>::iteratorKönnte z.B das bedeuten:
namespace std { template <class T> class list { int iterator; }; }oder auch das:
namespace std { template <class T> class list { typedef int* iterator; }; }Und das kann der Compiler nicht auseinanderhalten. Er nimmt Standardmässig an, dass es sich nicht um einen Typen handelt, ausser du sagst es ihm mittels typename.
-
voidpointer schrieb:
Tut mir leid, verstehe das nicht ganz oO
Dann schlag mal in deinem C++-Buch nach.

voidpointer schrieb:
Hat das dann hier eine neue Bedeutung?
Kommt drauf an. An welche Bedeutung hast du denn gedacht? Es bedeutet: "Achtung das was danach kommt, ist ein Typbezeichner"
voidpointer schrieb:
Und: warum könnte iterator auch eine Membervariable sein? Ist das Problem, dass der Iterator wissen muss, worauf er zeigt, während das die Liste nicht wissen brauch? Im Grunde genommen ist es für die Liste doch auch relevant, oder nicht?
Nicht der
iteratorselber, sondern der Bezeichner.Nimm folgendes Beispiel:
struct A { typedef int x; } struct B { static int x; } int B::x = 42; template <typename T> struct TPL1 { typename T::x variable; } template <typename T> struct TPL2 { void foo() { T::x = 5; } }Bei dem
T::xist nicht klaar, ob es sich jetzt um eine Variable, oder um einen Typ handelt. Und damit der Compiler einen Syntax-Check durchführen kann, geht er davon aus, es ist eine Variable. Willst du, dassT::xein Typ ist, dann muss eintypenamedavor.Edit: Hmm... zu langsam

-
Ok, vielen Dank soweit! Ich denke, ich habe es verstanden. Mein C++-Buch hat über 800 Seiten aber das stand da nicht.
Könnte man das typename noch mit Hilfe von Typedefs für Iteratoren weglassen? Mein Compiler akzeptiert das:
typedef typename list<A_Entry*>::iterator iterator;Ist das so ok? Und ist der Name "iterator" ungünstig, da es in manchen Fällen zu problemen kommen könnte?
-
voidpointer schrieb:
Ok, vielen Dank soweit! Ich denke, ich habe es verstanden. Mein C++-Buch hat über 800 Seiten aber das stand da nicht.
Könnte man das typename noch mit Hilfe von Typedefs für Iteratoren weglassen? Mein Compiler akzeptiert das:
typedef typename list<A_Entry*>::iterator iterator;Ist das so ok? Und ist der Name "iterator" ungünstig, da es in manchen Fällen zu problemen kommen könnte?
Das ist so OK. Wegen den Namen musst du hald selber wissen. Ich persönliche einen spezielleren Namen, der auf den Zweck des Containers hinweist.