Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Templates...

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
07.12.2009, 13:04 Uhr
Lotec



Hallo Leute,

ich habe hier die folgende Klassentemplate:

template<typename Key>
class MapTL : public std::map<Key, IterationNumber>
{
public:
void removeHazard(IterationNumber iter)
{
for(iterator it = begin(); it != end(); it++) //line 23 ist hier!
{
...Code...
}
};

ich kriege die folgenden Fehlermeldungen:

/home/lotec/ATS_2/ats/include/ATS/MapTL.h:23: error: ‘iterator’ was not declared in this scope
/home/lotec/ATS_2/ats/include/ATS/MapTL.h:23: error: expected ‘;’ before ‘it’
/home/lotec/ATS_2/ats/include/ATS/MapTL.h:23: error: ‘it’ was not declared in this scope
...

Das war g++. Unter MSVS 2008 geht es einwandfrei. Kann mir jemand bitte erklären, was da abläuft? Ich bin leider kein Spezialist für Templates

Dieser Post wurde am 07.12.2009 um 13:09 Uhr von Lotec editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
07.12.2009, 14:38 Uhr
~Bean
Gast


probiere es mal mit

for(typename iterator it = begin(); it != end(); it++)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
07.12.2009, 14:50 Uhr
Lotec



nope, ich krieg dann folgendes:

/home/lotec/ATS_2/ats/include/ATS/MapTL.h: In member function ‘void ATS::MapTL<Key>::removeHazard(ATS::IterationNumber)’:
/home/lotec/ATS_2/ats/include/ATS/MapTL.h:28: error: expected nested-name-specifier before ‘iterator’
/home/lotec/ATS_2/ats/include/ATS/MapTL.h:28: error: expected ‘(’ before ‘iterator’
/home/lotec/ATS_2/ats/include/ATS/MapTL.h:28: error: expected ‘;’ before ‘iterator’

oder meinst du etwas Bestimmtes anstelle von typename?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
07.12.2009, 14:57 Uhr
Lotec



Was ich noch sagen sollte: die Geschichte funktioniert, wenn die Klasse nicht templated ist. scheint so, als ob die Vererbung vom iterator wegen der Template scheitert
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
07.12.2009, 14:57 Uhr
0xdeadbeef
Gott
(Operator)


Der MSVC verhält sich hier nicht standardkonform. Wenn das eine Ausnahme ist, das Verhalten in im Standard definierten Situationen aber dem Standard entspricht, kann dich solcher Code in Teufels Küche bringen.

Zitat von ISO/IEC 14882:2003 14.6.2 (3):

In the definition of a class template or a member of a class template, if a base class of the class template depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member. [Example:

C++:
        typedef double A;
        template<class T> class B {
                   typedef int A;
        };
        template<class T> struct X : B<T> {
                   A a;                              // a has type double
        };


The type name A in the definition of X<T> binds to the typedef name defined in the global namespace scope, not to the typedef name defined in the base class B<T>. ] [Example:

C++:
     struct A {
             struct B { /* ... */ };
             int a;
             int Y;
    };

    int a;

    template<class T> struct Y : T {
             struct B { /* ... */ };
             B b;                                  // The B defined in Y
             void f(int i) { a = i; }              // ::a
             Y* p;                                 // Y<T>
    };

    Y<A> ya;


The members A::B, A::a, and A::Y of the template argument A do not affect the binding of names in Y<A>. ]


Du wirst die typedefs, die du brauchst, von Hand importieren müssen, also

C++:
template<typename Key>
class MapTL : public std::map<Key, IterationNumber>
{
public:
  typedef std::map<Key, IterationNumber> base_t;
  typedef typename base_t::iterator iterator;
  typedef typename base_t::const_iterator const_iterator;
  // ...
};


Ich nehme an, dass die Überlegung hinter diesem Verhalten ist, dass Templates Spezialisierungen erlauben, so dass beim Ableiten von einer Klassenvorlage unbekannt ist, beispielsweise "iterator" in allen Konkretisierungen ein Typname oder überhaupt vorhanden ist.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 07.12.2009 um 15:05 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
07.12.2009, 15:36 Uhr
Lotec



0xdeadbeef,

es hat funktioniert, Danke!

[emotionen an] templates... [emotionen aus]
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
07.12.2009, 15:57 Uhr
0xdeadbeef
Gott
(Operator)


Oh, templates sind toll. Sehr nützlich. Man benötigt halt nur ein bisschen Fingerspitzengefühl für sie. Oh, und Erfahrung in funktionaler Programmierung ist ebenfalls sehr nützlich.

Übrigens...von STL-Containern abzuleiten ist ziemlich schlechter Stil und ziemlich gefährlich, weil sie keine virtuellen Destruktoren haben. Sobald du damit Polymorphie betreibst, geht dir sehr schnell Speicher verloren, ganz abgesehen davon, dass die Basisklasse nicht das benötigte Interface zur Verfügung stellt. Wahrscheinlich bist du mit einer Fuktionsvorlage besser dran.
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
07.12.2009, 16:30 Uhr
Lotec




Zitat von 0xdeadbeef:


Übrigens...von STL-Containern abzuleiten ist ziemlich schlechter Stil und ziemlich gefährlich, weil sie keine virtuellen Destruktoren haben. Sobald du damit Polymorphie betreibst, geht dir sehr schnell Speicher verloren, ganz abgesehen davon, dass die Basisklasse nicht das benötigte Interface zur Verfügung stellt. Wahrscheinlich bist du mit einer Fuktionsvorlage besser dran.



Gut, dass du es sagst, das hab ich nicht gewusst. In Java hab ich früher immer so gemacht und fand es toll auf die Weise. Ich glaube, in meinem Fall ist es OK, denn ich brauche keine Destruktoren in der Klasse, aber für die Zukunft bin ich jetzt besser gerüstet
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
07.12.2009, 18:55 Uhr
0xdeadbeef
Gott
(Operator)


Äh...einen Destruktor hat die Klasse sowieso. Wenn du keinen angibst, erstellt der Compiler einen für dich (abgesehen von POD-Structs), der die Member zerstört.

Wie dem auch sei, es wird so lange funktionieren, wie du die Klasse nicht polymorphisch benutzt. Sobald du etwa

C++:
std::map<int, IterationNumber> *p = new MapTL<int>();

// ...

delete p; // <-- undefiniertes Verhalten


machst, geht es in die Hose.

Natürlich ist das ganze insofern gefährlich, als dass eine Ableitung geradezu dazu einlädt, solche Dinge zu machen.

Oh, und std::map ist intern ein Baum, also ist das Durchlaufen aller Iteratoren denkbar langsam. Meinst du vielleicht

C++:
iterator it = find(iter);


?
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
07.12.2009, 19:16 Uhr
Lotec




Zitat von 0xdeadbeef:
Äh...einen Destruktor hat die Klasse sowieso. Wenn du keinen angibst, erstellt der Compiler einen für dich (abgesehen von POD-Structs), der die Member zerstört.

Wie dem auch sei, es wird so lange funktionieren, wie du die Klasse nicht polymorphisch benutzt. Sobald du etwa

C++:
std::map<int, IterationNumber> *p = new MapTL<int>();

// ...

delete p; // <-- undefiniertes Verhalten


machst, geht es in die Hose.

Natürlich ist das ganze insofern gefährlich, als dass eine Ableitung geradezu dazu einlädt, solche Dinge zu machen.



Ich habs jetzt so umgestellt, dass std::map ein Attirbut der MapTL ist. Ist schon verrückt, was alles schief gehen kann bei C++...


Zitat von 0xdeadbeef:

Oh, und std::map ist intern ein Baum, also ist das Durchlaufen aller Iteratoren denkbar langsam. Meinst du vielleicht

C++:
iterator it = find(iter);


?


ne-ne... Primär dient es dazu, die Elemente schnell durch ihre Schlüsseln zu finden, eben mit iterator iter = find(key). Aber ab und zu muss ich durch die ganze map iterieren, um sie zu reinigen. Was meinst du eigentlich mit langsam? Klar, es sind rekursive Aufrufe drin usw. und das Ganze ist schon langamer als ein Array durchzulaufen, aber komplexitätstechnisch ist es auch nur lineare Zeit.

Dieser Post wurde am 07.12.2009 um 19:23 Uhr von Lotec editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: