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;
}