std::map, std::map::iterator und templates...
-
Hallo zusammen
Ich kriege momentan folgenden Code einfach nich' so zusammen, dass er kompiliert. Ich nehme an, der Fehler ist eine Folge meines mangelhaften Wissens über die Memberklasse iterator plus etwas mit Templates, aber ich kriegs gerade nicht raus.
Dies ist mein bisheriger, fehlerhafter Code:
template<class T, class U> class wrapamap{ class wam_value{ U eintrag; bool zusatz; (...einige Methoden...) }; public: void ichMachWasMitJedemEintrag(); private: std::map<T,wam_value> MyMap; }; template<class T, class U> void wrapamap<T,U>::ichMachWasMitJedemEintrag() { typename std::map<T,wam_value>::iterator walkABit; //dies krieg ich nich so hin, damit for( walkABit=MyMap.begin(); walkABit!=MyMap.end(); walkABit++ ) // diese zuweisung und der vergleich funktionieren { ... } }Ich krieg die definition des iterators nich richtig hin, kann wer helfen?
Merci!
-
Hallo hannahmontana!
Ich vermute du willst sowas:
template<class T, class U> class wrapamap{ class wam_value{ U eintrag; bool zusatz; }; public: void ichMachWasMitJedemEintrag(); private: std::map<T,wam_value> MyMap; }; template<class T, class U> void wrapamap<T,U>::ichMachWasMitJedemEintrag() { typedef typename std::map<T, typename wrapamap<T,U>::wam_value>::iterator walkABit; //dies krieg ich nich so hin, damit for(walkABit it=MyMap.begin(); it!=MyMap.end(); it++ ) // diese zuweisung und der vergleich funktionieren { // ... } }bzw. schöner:
template<class T, class U> class wrapamap{ class wam_value{ U eintrag; bool zusatz; }; public: void ichMachWasMitJedemEintrag(); typedef std::map<T,wam_value> map_type; private: map_type MyMap; }; template<class T, class U> void wrapamap<T,U>::ichMachWasMitJedemEintrag() { typedef typename wrapamap<T,U>::map_type::iterator walkABit; //dies krieg ich nich so hin, damit for(walkABit it=MyMap.begin(); it!=MyMap.end(); it++ ) // diese zuweisung und der vergleich funktionieren { // ... } }Gruß,
XSpille
-
XSpille schrieb:
bzw. schöner:
oder auch schön
template<class T, class U> class wrapamap{ struct wam_value{ U eintrag; bool zusatz; }; public: typedef std::map<T,wam_value> MyMap; static void ZusatzAnzeigen(typename MyMap::const_reference r) { std::cout << r.second.zusatz << "\n"; } template<typename Func> void ichMachWasMitJedemEintrag(Func wasDenn) { std::for_each(map_.begin(), map_.end(), wasDenn); } private: MyMap map_; }; int main() { typedef wrapamap<int, int> wrap; wrap m; m.ichMachWasMitJedemEintrag(wrap::ZusatzAnzeigen); return 0; }
-
Hallo zusammen, danke für die bisherigen Antworten, die bringen mich allerdings nicht weiter.
Ich hab' gerade gemerkt, dass ich den entscheidenden Punkt gestern Nacht beim Abschreiben des Codes vergessen hab': Die Funktion ist const.
(In der oben geposteten Version funktionierts). Wegen des const krieg ich ein "no match for 'operator=', komm ich da irgendwie von weg(und wie?) oder funktioniert der iterator member type nicht auf konstanten objekten? ich hab leider nichts gefunden wie der map::iterator in der stl umgesetzt ist.editierter code:
template<class T, class U> class wrapamap{ class wam_value{ U eintrag; bool zusatz; (...einige Methoden...) }; public: void ichMachWasMitJedemEintrag() const; private: std::map<T,wam_value> MyMap; }; template<class T, class U> void wrapamap<T,U>::ichMachWasMitJedemEintrag() const { typename std::map<T,wam_value>::iterator walkABit; //dies krieg ich nich so hin, damit for( walkABit=MyMap.begin(); walkABit!=MyMap.end(); walkABit++ ) // diese zuweisung und der vergleich funktionieren { ... } }Merci!
-
Du kannst auf member-Variablen (ohne const_cast) keine verändernden Operationen
durchführen.Der iterator erlaubt aber eine Veränderung der Elemente in der map.
Wenn du stattdessen const_iterator verwendest, sind diese nicht möglich.
Beim Dereferenzieren des const_iterators kriegst du dann natürlich ein const Objekt zurück.EDIT: Wenn ich heute morgen schon wach gewesen wäre, hätte mir auffallen sollen,
dass dein Code funktioniert
-
XSpille schrieb:
Du kannst auf member-Variablen (ohne const_cast) keine verändernden Operationen
durchführen.Der iterator erlaubt aber eine Veränderung der Elemente in der map.
Wenn du stattdessen const_iterator verwendest, sind diese nicht möglich.
Beim Dereferenzieren des const_iterators kriegst du dann natürlich ein const Objekt zurück.EDIT: Wenn ich heute morgen schon wach gewesen wäre, hätte mir auffallen sollen,
dass dein Code funktioniert
Yes, merci vielmals! Ich hab den const_iterator nich gekannt und gehofft, dass iterator eine const-Überladung beinhaltet. Mit const_iterator funktionierts perfekt!
Aus reinem Interesse: Wo hätte ich einen const_cast anbringen müssen, um das Ganze ohne const_iterator zum laufen zu bringen? Ich hab dahingehend einiges versucht...
Gruss
Btw. Ging mir ähnlich als ich den ersten Beitrag geschrieben hab

-
hannahmontana schrieb:
Wo hätte ich einen const_cast anbringen müssen, um das Ganze ohne const_iterator zum laufen zu bringen?
Ungetestet (Hab gerade keinen Compiler hier):
template<class T, class U> void wrapamap<T,U>::ichMachWasMitJedemEintrag() const { // Ich bin mir nicht sicher, ob du vor dem wam_value das "typename wrapamap<T,U>::" brauchst // typename std::map<T, wam_value>& MyMap2(const_cast<typename std::map<T, wam_value>& >(MyMap)); typename std::map<T,typename wrapamap<T,U>::wam_value>& MyMap2(const_cast<typename std::map<T,typename wrapamap<T,U>::wam_value>& >(MyMap)); typename std::map<T,wam_value>::iterator walkABit; //dies krieg ich nich so hin, damit for( walkABit=MyMap2.begin(); walkABit!=MyMap2.end(); walkABit++ ) // diese zuweisung und der vergleich funktionieren { ... } }Aber meistens deutet ein const_cast auf einen Fehler in deinem Programm-Design
hin.EDIT: Du kannst natürlich auch this casten, nur dann macht das const wohl
gar keinen Sinn mehr
EDIT2: Je länger ich drüber nachdenke, glaub ich, du brauchst das "typename wrapamap<T,U>::"
EDIT3: Ja, du brauchst es
(Immernoch ungetestet)
-
std::map<...>::iterator it = const_cast<std::map<...>&>(MyMap).begin();Der bessere Weg wäre aber MyMap mutable zu machen.
class mapwrap { //... mutable MapType MyMap; };Damit kannst du MyMap auch in konstanten Methoden verändern. Sowas kann auch durchaus Sinn machen, wenn durch Aufrufen der Methode das Objekt nicht logisch verändert wird.
-
XSpille schrieb:
EDIT2: Je länger ich drüber nachdenke, glaub ich, du brauchst das "typename wrapamap<T,U>::"
EDIT3: Ja, du brauchst es
(Immernoch ungetestet)Ich hab das kurz ausprobiert mit gcc, Resultat: Man braucht es nicht!

Dies:
XSpille schrieb:
Ungetestet (Hab gerade keinen Compiler hier):
typename std::map<T, wam_value>& MyMap2(const_cast<typename std::map<T, wam_value>& >(MyMap));Funktioniert ohne Probleme. Wohl gleicher namespace?
@brotbernd: Merci für den Input. Da muss man dann aber langsam schon extrem aufpassen nichts durcheinander zu kriegen.. Aber für das Zwischenspeichern von aufwändig berechneten, wiederverwendbaren Resultaten natürlich sehr hilfreich.
-
hannahmontana schrieb:
XSpille schrieb:
EDIT2: Je länger ich drüber nachdenke, glaub ich, du brauchst das "typename wrapamap<T,U>::"
EDIT3: Ja, du brauchst es
(Immernoch ungetestet)Ich hab das kurz ausprobiert mit gcc, Resultat: Man braucht es nicht!

Ich brauch es wohl, da ich es sonst nicht verstehe :p
Danke, dass du es kurz getestet hast und das Ergebnis auch postet

-
Das Schlüsselwort
typenamebenötigst du nur bei abhängigen Namen. Das wäre zum Beispiel (angenommen, mindestens ein Typ vonKeyundValueist ein Templateparameter):typename std::map<Key, Value>::iteratornicht aber:
std::map<Key, Value>