'Incrementing iterator from end to begin
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?
Solution 1:[1]
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;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
