2016-06-28 15 views
3

Я (вперед) итерации по std :: map и хотел бы найти, если итератор указывает на второй последний элемент. Кажется, я не могу найти, как это сделать.Проверьте, является ли итератор std :: map указывает на второй последний элемент

У меня есть:

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

Где TDateFileInfoMap находится станд :: Карта

Я получаю:

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>] 

Означает ли это, я не могу сравнить вперед и обратный итератор?

Как определить, если передний итератор указывает на второй последний элемент?

+1

Как насчет 'tsFile + 2 == mFileInfoMap.end()'? – lorro

ответ

2

Означает ли это, что я не могу сравнивать передний и задний итератор?

Да, вы не можете сравнить их напрямую.

Вы можете использовать base(), чтобы получить базовый итератор базы.

Возвращает базовый итератор базы. То есть std::reverse_iterator(it).base() == it.

Основание итератора относится к элементу, который находится рядом (с точки зрения std::reverse_iterator::iterator_type) к элементу, reverse_iterator данный момента указует. Это &*(rit.base() - 1) == &*rit.

например.

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

КСТАТИ: mFileInfoMap.rbegin() + 1 не будет компилироваться, так как итератор std::map не RandomAccessIterator. Вы могли бы написать:

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

Обратите внимание, что мы не проверяя, является ли карта пуста или имеет только один элемент.

+0

Выполнение этого, кажется, возвращает последний элемент, а не второй. Но, глядя на определение base(), я не уверен, почему это так ... – Danny

+0

@ Danny [Here] (http://en.cppreference.com/w/cpp/iterator/reverse_iterator) объяснения обратный итератор. – songyuanyao

3

std::map's итерационный тип BidirectionalIterator. Просто уменьшает end итератора дважды - первый, чтобы получить последний элемент, поскольку m.end() возвращает итератор на после конечного положения, а затем снова, чтобы получить второй-последний элемент:

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

Тогда вы можете просто проверить для равенство с результирующим итератором:

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

see it live on Coliru

Естественно, вы должны проверить, что отображение имеет два элемента первый если он в вашей программе не гарантируется другая логика.

+2

Последовательный 'operator -' вряд ли читаем. Почему бы не использовать 'auto back = std :: prev (m.end(), 2)'? – KABoissonneault

+0

@ KABoissonneault, потому что это не пришло мне в голову. Спасибо, исправлено. – jaggedSpire

0

Простое решение для передних итераторов:

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()); 
}