Fehler in nem stl-header
-
Freitag, 24. August 2012 22:20
Hmm - nachdem VC2010 Express neu installiert habe, ist auch wieder ein Fehler da, den ich vorher durch krudes hacking gelöst hatte: Ein std::multiset::iterator ergibt dereferenziert eine const-referenz statt einer referenz:
CAttribute& newAttribute(IAttribute::key_t key) { while(*key && isspace(*key)) ++key; attributes_t::iterator i = m_Attributes.insert(CAttribute(key)); return *i; }Ergibt einen Fehler: "... loses qualifier..."
Beim durchsehen der STL-Header landet man dann bei folgender Stelle (xtree):
// TEMPLATE CLASS _Tree template<class _Traits> class _Tree : public _Tree_val<_Traits> { // ... typedef _Tree_const_iterator<_Mybase> const_iterator; typedef typename _STD tr1::conditional< _STD tr1::is_same<key_type, value_type>::value, const_iterator, _Tree_iterator<_Mybase> >::type iterator;Der Iterator wird also ggf. als const_iterator definiert. Klar, dass das nen Fehler ergibt - nur: was war wohl der Gedanke dabei?!? Wieso sollte es einen unterschied machen, ob key und value vom selben Typ sind? Und weshalb sollte das dazu führen, dass ein iterator const sein soll/kann? Mein krudes hacking im vorigen bestand darin, den const_iterator zu kastrieren, indem ich das derefernzieren in einer einfachen referenz statt in einer const-referenz resultieren ließ - das ist nüchtern betrachtet natürlich unsinn, was aber gut leserlich... Jedenfalls funktionierts gut, wenn man den typedef oben in
typedef typename _Tree_iterator<_Mybase> iterator;
ändert.
.... Ich: *haps*
Alle Antworten
-
Montag, 27. August 2012 05:55
-
Montag, 27. August 2012 07:28Moderator
Das ist kein Fehler.
sets liefern nur noch const Referenzen. sets dürfen per Definition nicht mehr geändetr werden. Das ist IMHO seit VC-2010 so. In 2008 war die Referenz noch non-const.
Wenn Du da was ändern musst, dann nimm eine map!
Nachtrag: Ich habe auch den Artikel gefundenin dem das beschrieben ist (problem 3)
http://blogs.msdn.com/b/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx
Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
- Als Antwort vorgeschlagen Martin RichterMVP, Moderator Montag, 27. August 2012 07:28
- Bearbeitet Martin RichterMVP, Moderator Montag, 27. August 2012 07:32
-
Montag, 27. August 2012 13:00
Ich will aber keine map, ich will ein set haben... Spass beiseite: so, wie das nachdem ich Martin's link gelesen habe, "richtig" ist, verursacht
#include <set> void tstfn() { typedef std::multiset<int> set_t; set_t intSet; intSet.insert(1); intSet.insert(2); intSet.insert(3); set_t::iterator i = intSet.begin(); const int& a = (*i); int& b = (*i); }einen Fehler und zeigt, warum das nicht richtig ist. In dem Beispiel würde mit b der key geändert werden können. Da, wo der nicht-Fehler zuerst auftrat war das key-attribute für den aufrufer der funktion nur read-only verfügbar (einschränkung durch die api), was für mich einen const-cast hinreichen rechtfertigt.
Ein Blick in stl-spec ergibt: "In some Associative Containers, Simple Associative Containers, the <tt>value_type</tt> and <tt>key_type</tt> are
the same: elements are their own keys. In others, the key is some specific part of the value." Ohne weitere Erläuterung, was others wohl sind - gibt's nicht. Der Witz: man will eine Menge von Objekten haben und eines der Objekt-Attribute soll das Schlüsselattribut sein. Warum gibts das so nicht? Wäre doch einfach zu implementieren mit einem pointer-to-member-Konstrukt - man könnte nur nicht die Unveränderbarkeit des Schlüsselattributs sicherstellen. Und das scheint wohl mal der gedanke gewesen zu sein: Der iterator wurde früher anscheinend eher als der wert interpretiert und jetzt als schlüssel. Wer schreibt eigentlich die stl-definitionen? Key und Schlüssel als das selbe zu definieren scheint mir doch eher der realisierung geschuldet zu sein. key als f(value) zu definieren wäre so gesehen doch das mittel der wahl gewesen: mit dem spezialfall, dass f = id. Dann würde es auch Sinn machen, set als Associative Container definiert zu haben, statt einfach als den nicht-existierenden Sorted Container.Kann man nach der Änderung also mit den angeklungenden "others" rechnen?
...Und dann sagte ich mir: "Heiko, ich weiss es nicht."
- Bearbeitet Heiko Lewin Montag, 27. August 2012 13:03
-
Montag, 27. August 2012 13:17Moderator
Ich würdenicht mit dem "Erscheinen von others" rechnen. Bzgl. des Standard wüsste ich nichtdas hier etwas im Schwange wäre.
Ansonsten steht es Dir doch frei den const wegzucasten. Bzw. eine eigene template Klasse zu bauen mit gettern settern, die das ganze verbergen.
Der Grundsatz hier ist eben "Sicherheit zuerst" und die Möglichkeit "unbeabsichtigt" den Key mit durch ein Assignment zu ändern ist eben hoch.Es ist wie es ist: set::iterator sind readonly Punkt. Wege drum herum gibts genug.
Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
-
Montag, 27. August 2012 13:26
"Es ist wie es ist: set::iterator sind readonly Punkt." Wobei das ja eine Folgeerscheinung ist: Die Definition erfordert das nicht direkt. "id(key,value), const(key) => const(value)". Wozu dann eigentlich die Trennung von key und value in der Definition?

