2016-06-28 6 views
3

Ich bin (vorwärts) über eine std :: map iterieren und würde gerne herausfinden, ob der Iterator auf das vorletzte Element zeigt. Ich kann nicht finden, wie man das überall macht.Überprüfen Sie, ob Iterator zu std :: Punkte auf zweitletztes Element mappen

Ich habe:

bool 
isSecondLastFile(const TDateFileInfoMap::const_iterator &tsFile) 
{ 
    TDateFileInfoMap::reverse_iterator secondLastIt = mFileInfoMap.rbegin() + 1; 
    return (tsFile == secondLastIt); 
} 

Wo TDateFileInfoMap ist std :: map

Ich erhalte:

error: no match for ‘operator==’ in ‘tsFile == secondLastIt’ 
/usr/lib/gcc/i686-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_tree.h:287: note: candidates are: bool std::_Rb_tree_const_iterator<_Tp>::operator==(const std::_Rb_tree_const_iterator<_Tp>&) const [with _Tp = std::pair<const long int, TFileInfo>] 

Heißt das, ich kann nicht bedeuten, die vergleichen vorwärts und umgekehrter Iterator?

Wie finde ich heraus, ob der Vorwärtsiterator auf das zweitletzte Element zeigt?

+1

Wie wäre es 'tsFile + 2 == mFileInfoMap.end()'? – lorro

Antwort

2

Bedeutet das, dass ich den Vorwärts- und Rückwärts-Iterator nicht vergleichen kann?

Ja, Sie können sie nicht direkt vergleichen.

Sie können base() verwenden, um den zugrunde liegenden Basisiterator abzurufen.

Gibt den zugrunde liegenden Basisiterator zurück. Das ist std::reverse_iterator(it).base() == it.

Die Basis Iterator bezieht sich auf das Element, das (aus der Perspektive std::reverse_iterator::iterator_type) als nächstes zu dem Element der reverse_iterator gerade zeigt. Das ist &*(rit.base() - 1) == &*rit.

z.B.

return (tsFile == (++secondLastIt).base()); 

BTW: mFileInfoMap.rbegin() + 1 wird nicht kompiliert, da der Iterator von std::map ist nicht RandomAccessIterator. Man könnte schreiben:

TDateFileInfoMap::reverse_iterator secondLastIt = mFileInfoMap.rbegin(); 
++secondLastIt; 

Bitte beachte, dass wir die Überprüfung sind nicht, ob die Karte leer ist oder nur ein Element.

+0

Dies scheint das letzte Element, nicht vorletzte, zurückzugeben. Aber ich betrachte die Definition von Base() Ich bin mir nicht sicher, warum das ... – Danny

+0

@Danny [Here] (http://en.cppreference.com/w/cpp/iterator/reverse_iterator) ist die Erklärungen über umgekehrter Iterator. – songyuanyao

3

std::map's Iteratortyp ist BidirectionalIterator. Nur verringert den end Iterator zweimal - zuerst das letzte Element zu erhalten, da m.end() einen Iterator auf dem nach der Endposition zurückkehrt und dann wieder das vorletzte Element zu erhalten:

auto penultimate = std::prev(m.end(), 2); 

Dann können Sie einfach überprüfen Gleichheit mit dem resultierenden Iterator:

auto it = m.begin(); 
it == penultimate; 

see it live on Coliru

Natürlich sollten Sie prüfen, ob die Karte zwei Elemente zuerst, wenn es ist nicht durch andere Logik in Ihrem Programm garantiert.

+2

Fortlaufende 'operator -' sind kaum lesbar. Warum nicht 'auto back = std :: prev (m.end(), 2)'? – KABoissonneault

+0

@KABoissonneault weil es mir nicht eingefallen ist. Danke und behoben. – jaggedSpire

0

Eine einfache Lösung für die Vorwärts Iteratoren:

template <typename ForwardIterator> 
inline bool isNthLast(std::size_t n, ForwardIterator pos, ForwardIterator last) { 
    for(;; --n, ++pos) { 
     if(n == 0) 
      return (pos == last); 
     if(pos == last) 
      return false; 
    } 
} 

bool isSecondLastFile(TDateFileInfoMap::const_iterator sFile) { 
    return isNthLast(2, sFile, mFileInfoMap.end()); 
} 
Verwandte Themen