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

Tags:

C++

Stl

Iterator