Seite 1 von 1

Anzahl Elemente zwischen zwei STL-Iteratoren einer QMap

Verfasst: 28. April 2011 04:15
von Spinoza
Hallo zusammen,
ich habe zwei Stellen in einer QMap<double, double> mittels zweier STL-Style-Iteratoren ermittelt und möchte nun herausfinden, wieviele Elemente dazwischen liegen. Laut Qt-Hilfe (Qt 4.6: Generic Containers -> STL-Style Iterators) geht das, indem die zwei Iteratoren subtrahiert werden:
i - j Returns the number of items between iterators i and j
Bei mir gibt's dabei jedoch den Fehler
/usr/include/qt4/QtCore/qmap.h:343: error: ‘QMap<Key, T>::const_iterator::operator bool() const [with Key = double, T = double]’ is private
mainwindow.cpp:402: error: within this context
Wobei der Code testweise so aussah:

Code: Alles auswählen

  QMap<double, double> m;
  m.insert(1, 1);
  m.insert(2, 2);
  m.insert(3, 3);
  m.insert(4, 4);
  QMap<double,double>::const_iterator it1 = m.upperBound(1.5);
  QMap<double,double>::const_iterator it2 = --m.lowerBound(3.5);
  int n = it2 - it1; // Zeile 402
  qDebug() << *it1 << *it2 << n;
Mach ich hier was falsch oder ist da ein Fehler in der Qt-Hilfe bzw. gar dem Qt-Code?

Gruß, Spinoza

Re: Anzahl Elemente zwischen zwei STL-Iteratoren einer QMap

Verfasst: 28. April 2011 08:22
von solarix
Spinoza hat geschrieben: Mach ich hier was falsch oder ist da ein Fehler in der Qt-Hilfe bzw. gar dem Qt-Code?
Weder noch...

Es ist nie gut, wenn der Source-Code bei der Anwendung einer Klasse von irgendwelchen internen Algorithmen abhängt. Die Anwendung von QMap sollte also unabhängig von der internen Architektur sein. Diese Kapselung kann man doppelt begründen:

- Falls die Entwickler von QMap eines Tages auf die Idee kommen, die Daten anders zu organisieren, bist du am A...

- Beim Lesen des Anwendercodes könnte man das Ergebnis nur verstehen, wenn man den internen Algorithmus kennt... und das ist immer schlecht.

Daher haben die Trolls diesen Operator im Falle von QMap "private" gemacht. Der von dir geschriebene Absatz der Qt-Doku dient ja nur zur Übersicht.. das bedeutet nicht, dass es keine Ausnahmen (mehr oder weniger Operatoren) bei bestimmten Containern gibt...

hth!

Verfasst: 28. April 2011 10:16
von brax
Hmm, also eigentlich besagt die Fehlermeldung dass der implizite Cast operator bool() private ist, dort ist gar nicht die Rede vom operator-. Wenn man in den Code von QMap guckt stellt man auch tatsächlich fest, dass überhaupt kein operator-, der einen anderen QMap::(const_)iterator bekommt definiert ist. Daher versucht der Compiler, das für ihn nächstliegende, in dem Fall nämlich per implizitem Cast die beiden Iteratoren zu bools zu machen. Dieser Operator ist allerdings private, daher die Fehlermeldung.

Beim Blick in qlist.h finden wir den angesprochenen operator- :

Code: Alles auswählen

205: inline int operator-(iterator j) const { return int(i - j.i); }
bzw.

Code: Alles auswählen

243: inline int operator-(const_iterator j) const { return i - j.i; }

Ich würde Spinoza also zustimmen, dass an der Stelle die Docu etwas irreführend ist, weil eben die Zeile
i - j Returns the number of items between iterators i and j
für QMap::(const_)iterator nicht zutrifft.

Verfasst: 28. April 2011 12:27
von Spinoza
Okay, danke für eure Hilfe schonmal.
Das heisst, ich muss wohl oder übel sämtliche Elemente dazwischen selber durcheiern à la:

Code: Alles auswählen

n = 0;
while (it1 != it2)
{
  ++it1;
  ++n;
}
Oder gibt's was schöneres? QMap ist ja intern als Skiplist implementiert, hat man darüber eventuell schnelleren und eleganteren Zugriff auf die Elementzahl zwischen zwei Einträgen?
Ich habe nämlich rund 5000 Einträge und die obere Passage brauche ich in einem paintEvent, und das Ganze sollte flüssig laufen. Deshalb bin ich so pingelig.

Verfasst: 28. April 2011 12:33
von Christian81
Ich bin mir ziemlich sicher dass STL an der Stelle auch nichts weiter macht als solange den einen Iterator hochzuzählen bis der andere erreicht ist und dann die Anzahl zurückgibt. Alles andere gibt die interne Datenstruktur gar nicht her.
Evtl. ist QMap/map nicht der richtige Datencontainer für die Aufgabe ...