Home > Net >  Incrementing iterator from end to begin
Incrementing iterator from end to begin

Time:05-06

I want to iterate over a vector and when reaching the end it should loop back to the front.

This is a small example which does not compile

#include <vector>

std::vector<int>::iterator Next(const std::vector<int>& vec, 
    const std::vector<int>::iterator it) 
{
    auto itNext = it 1;
    if (itNext == vec.end())
        itNext = vec.begin(); // breaks 
    return itNext;
}

int main()
{
    std::vector x{0, 2, 3, 4};
    auto it = x.begin() 1;        
    return *Next(x,it);
}

and here a godbolt link.

The issue arises because of no available conversion between vector::const_iterator (result of begin()) and vector::iterator. How can one fix this issue?

CodePudding user response:

You cannot convert a const_iterator to an iterator because this would break const-correctness.

You basically have two options. When it is ok to return a const_iterator then return a const_iterator:

#include <vector>

std::vector<int>::const_iterator Next(const std::vector<int>& vec, 
    std::vector<int>::const_iterator it) 
{
    auto itNext = it 1;
    if (itNext == vec.end())
        itNext = vec.begin();
    return itNext;
}

int main()
{
    std::vector x{0, 2, 3, 4};
    auto it = x.begin() 1;        
    return *Next(x,it);
}

You can only get a const_iterator from a const std::vector&. Hence if you want to return an iterator the vector has to be passes as non-const reference:

#include <vector>

std::vector<int>::iterator Next(std::vector<int>& vec, 
    std::vector<int>::iterator it) 
{
    auto itNext = it 1;
    if (itNext == vec.end())
        itNext = vec.begin(); 
    return itNext;
}

int main()
{
    std::vector x{0, 2, 3, 4};
    auto it = x.begin() 1;        
    return *Next(x,it);
}

To have both in one I would pass iterators and make the function a template, so it can be used with iterator or const_iterator. The function might grant you non-const access to the vectors elements, but for the function itself it doesn't matter that much if the iterators are const or not.

#include <vector>


template <typename IT>
IT Next(IT it,IT begin,IT end) {
    auto itNext = it 1;
    return (itNext == end) ? begin : itNext;
}

int main()
{
    std::vector x{0, 2, 3, 4};
    auto it = x.begin() 1;        
    auto it2 = Next(it,x.begin(),x.end());
    *it2 = 42;
}
  • Related