开发者

Peeking the next element in STL container

开发者 https://www.devze.com 2023-01-15 23:52 出处:网络
Is it possible to peek next element in a container which the iterator currently points to without changing the iterator?

Is it possible to peek next element in a container which the iterator currently points to without changing the iterator?

For example in std::set,

int myArray[]= {1,2,3,4};
set <int> mySet(myArray, myArra开发者_JAVA技巧y+4);
set <int>::iterator iter = mySet.begin();

//peek the next element in set without changing iterator.

mySet.erase(iter); //erase the element if next element is n+1


C++0x adds a handy utility function, std::next, that copies an iterator, advances it, and returns the advanced iterator. You can easily write your own std::next implementation:

#include <iterator>

template <typename ForwardIt>
ForwardIt next(ForwardIt it, 
               typename std::iterator_traits<ForwardIt>::difference_type n = 1)
{
    std::advance(it, n);
    return it;
}

You can use this in your example like so:

if (iter != mySet.end() && next(iter) != mySet.end() && *next(iter) == *iter + 1)
    mySet.erase(iter);


Not with iterators in general. An iterator isn't guaranteed to be able to operate non-destructively. The classic example is an Input Iterator that actually represents an underlying input stream.

There's something that works for this kind of iterator, though. A Forward Iterator doesn't invalidate previous copies of itself by the act of moving forward through the collection. Most iterators (including those for STL collections) are at least Forward Iterators, if not a more functional version- only Input Iterators or Output Iterators are more restricted. So you can simply make a copy of your iterator, increment the copy and check that, then go back to your original iterator.

So your peek code:

set <int>::iterator dupe = iter;
++dupe;
// (do stuff with dupe)


set <int>::iterator iter2 = iter;
++iter2;
int peekedValue = *iter2;


You can always make a copy of the iterator and advance the copy:

set <int>::iterator iter = mySet.begin();
set <int>::iterator iterCopy = iter;
iterCopy++;
if (*iterCopy == something)
  mySet.erase(iter);

But beware that iterCopy may no longer be valid once you erase iter.


for sequence containers (vector, deque, and list) you can call front which will give you a peek (more info on the lower part of this link).


This will not work for std::set as its nature does not allow for the [] operator, but for containers that do, you can do:

std::vector<int> v;
v.push_back(3);
v.push_back(4);
std::vector<int>::iterator it = v.begin(); 
std::cout << v[it - v.begin() + 1];

But this could be dangerous if it points to the last element in the container; but the same applies to the solution above. E.g. you'll have to make checks in both cases.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号