How do you keep advance() from going beyond end()?

S

solartimba

I am using the advance() auxiliary STL iterator function to move a map
iter forward, but I read that there is no check to keep the iter from
pointing past the end of the map. How is this problem normally
solved?
 
M

Moonlit

Hi,

Why not use the ++ operator and check if the iterator equals end() ?

for( map<anything>::iterator Iter = var.begin(); Iter != var.end();
++Iter )DoStuff( Iter );

Regards, Ron AF Greve.
 
M

Mike Wahler

solartimba said:
I am using the advance() auxiliary STL iterator function to move a map
iter forward, but I read that there is no check to keep the iter from
pointing past the end of the map. How is this problem normally
solved?

By doing the checking yourself. With a container which has
no random-access iterators (and thus no 'iterator arithmetic')
such as 'std::map', the obvious solution of e.g. checking the
'advance count' against 'end() - iterator' is not possible, so
something like 'std::distance' is needed to find out how far
you can go. But this function requires successively incrementing
the iterator, which is what advance does, so you've at least
doubled the processing. So imo one should only use 'advance'
with containers which support random access iterators where the
typically more efficient iterator arithmetic is possible (unless
your logic can somehow otherwise generate the 'max' advance value
beforehand.)

But anyway, just for fun, here's a 'bounds-checked advance' function:

#include <iostream>
#include <iterator>
#include <map>
#include <string>

template<typename Iter, typename Dist>
void checked_advance(Iter& it, // iterator to advance
const Iter& last, // 'highest' allowed iterator value
Dist dist) // requested advance distance
{
Dist maxdist(std::distance(it, last));
std::advance(it, dist > maxdist ? maxdist : dist);
}

int main()
{
std::map <int, std::string> numbers;
numbers[1] = "one";
numbers[2] = "two";
numbers[3] = "three";
numbers[4] = "four";
numbers[5] = "five";

std::map<int, std::string>::size_type count = 10;

std::map<int, std::string>::iterator it(numbers.begin()),
en(numbers.end()),
orig(it);

for(std::map<int, std::string>::size_type i = 0;
i < count; ++i, it = orig)
{
std::cout << "advance " << i << ":\n";
checked_advance(it, en, i);
std::cout << (it != en ? it->second : "[end]") << '\n';
}

return 0;
}

Output:
advance 0:
one
advance 1:
two
advance 2:
three
advance 3:
four
advance 4:
five
advance 5:
[end]
advance 6:
[end]
advance 7:
[end]
advance 8:
[end]
advance 9:
[end]


One could also change 'checked_advance()' to return the actual
distance advanced, if that value is useful.

HTH,
-Mike
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top