I saw some question on SO lately involving circular buffer, like a chain of descriptors for data transfer. All solutions involved lots of lines.
I wanted an implementation with as few lines as possible, as inspired by this answer. The idea is not to have a circular buffer but a usual container and a specific iterator able to wrap.
Question: Is it possible to achieve this with as few lines as in the example below or are there hidden pitfalls ?
- This code was intended to spin forever on a container which size do not change, more information about iterator validity under containers changes
Additional information after first answers / comments
Similar 2009 question on SO mentioned by Mercury Dime (the question uses the term cyclic or circulator and not circular)
EDIT: Corrections of the more evident errors / typos based on incomputable's answer
#include <iostream>
#include <list>
template <class BaseIter>
class CircularIterator:public BaseIter {
//inspired from https://stackoverflow.com/a/947754/3972710
BaseIter begin,end;
public:
CircularIterator(BaseIter b, BaseIter e ):BaseIter(b), begin(b), end(e) {}
CircularIterator & operator ++(void)
{
BaseIter::operator++();
if(*this == end)
BaseIter::operator=(begin);
return *this;
}
const CircularIterator operator ++(int)
{
const auto oldValue = *this;
this->operator++();
return oldValue;
};
CircularIterator & operator --(void) = delete;
const CircularIterator operator --(int) = delete;
};
int main()
{
std::list<int> intList = { 1, 2, 3};
CircularIterator<std::list<int>::iterator> circIter(intList.begin(),intList.end());
auto it = circIter++;
std::cout << *(it++) << "\n";
std::cout << *(it++) << "\n";
std::cout << *(it++) << "\n";
std::cout << *(it++) << "\n";
std::cout << "..." << "\n";
std::cout << "Hello world!\n";
return 0;
}
Original Code
#include <iostream>
#include <list>
using namespace std;
//C++11 at least
template <class baseIter>
class circularIterator:public baseIter {
//inspired from https://stackoverflow.com/a/947754/3972710
baseIter begin,end;
public:
circularIterator(baseIter b, baseIter e ):baseIter(b), begin(b), end(e) {}
baseIter & operator ++(void) { baseIter::operator++();
if(*this == end) baseIter::operator=(begin);
return *this;}
baseIter & operator ++(int) = delete;
};
int main()
{
list<int> intList = { 1, 2, 3};
circularIterator<list<int>::iterator> circIter(intList.begin(),intList.end());
cout << *circIter << endl;
cout << *(++circIter) << endl;
cout << *(++circIter) << endl;
cout << *(++circIter) << endl;
cout << *(++circIter) << endl;
cout << "..." << endl;
cout << "Hello world!" << endl;
return 0;
}
*(--circIter)
with circIter = begin will cause problems in your example. std::vector uses random access iterators, which will introduce even more problems. \$\endgroup\$ – Mercury Dime Jun 16 '17 at 1:55