Testing whether an iterator points to the last item?
Do this:
// defined in boost/utility.hpp, by the way
template <typename Iter>
Iter next(Iter iter)
{
return ++iter;
}
// first check we aren't going to kill ourselves
// then check if the iterator after itr is the end
if ((itr != Mine.end()) && (next(itr) == Mine.end()))
{
// points at the last element
}
That is all. Never gives you undefined behavior, works on all iterators, good day.
Wrap it up for fun:
template <typename Iter, typename Cont>
bool is_last(Iter iter, const Cont& cont)
{
return (iter != cont.end()) && (next(iter) == cont.end())
}
Giving:
if (is_last(itr, Mine))
If you're allergic to utility functions/nice looking code, do:
if ((itr != Mine.end()) && (itr + 1 == Mine.end()))
But you can't do it on non-random-access iterators. This one works with bidirectional iterators:
if ((itr != Mine.end()) && (itr == --Mine.end()))
And is safe since end() > itr
by the first check.
Yes, it's unsafe to decrement (or increment) end
if the vector may be empty. It's even somewhat unsafe to do the same with a pointer, although you'll probably get away with it.
To be really safe, use subtraction and values known to be safe and valid:
if ( Mine.end() - itr == 1 )
For compatibility with all forward iterators (such as in slist
, as opposed to random-access iterators of vector
and deque
), use
if ( std::distance( itr, Mine.end() ) == 1 )
or if you are concerned with performance but have bidirectional iterators (incl. any C++03 container)
if ( itr != Mine.end() && itr == -- Mine.end() )
or the truly anal case of only forward iterators and O(1) time,
if ( itr != Mine.end() && ++ container::iterator( itr ) == Mine.end() )
or if you are hellbent on cleverness to avoid naming the iterator class,
if ( itr != Mine.end() && ++ ( Mine.begin() = itr ) == Mine.end() )