C++ Circular buffer through Circular iterator 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 &lt;iostream&gt;
#include &lt;list&gt;

template &lt;class BaseIter&gt;
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 &amp; operator ++(void)
        {
            BaseIter::operator++();
            if(*this == end)
                BaseIter::operator=(begin);
            return *this;
        }
        const CircularIterator   operator ++(int)
        {
            const auto oldValue = *this;
            this-&gt;operator++();
            return oldValue;
        };

        CircularIterator &amp; operator --(void) = delete;
        const CircularIterator   operator --(int)  = delete;
};

int main()
{
    std::list&lt;int&gt; intList = { 1, 2, 3};
    CircularIterator&lt;std::list&lt;int&gt;::iterator&gt; circIter(intList.begin(),intList.end());

    auto it = circIter++;

    std::cout &lt;&lt; *(it++) &lt;&lt; "\n";
    std::cout &lt;&lt; *(it++) &lt;&lt; "\n";
    std::cout &lt;&lt; *(it++) &lt;&lt; "\n";
    std::cout &lt;&lt; *(it++) &lt;&lt; "\n";
    std::cout &lt;&lt; "..." &lt;&lt; "\n";
    std::cout &lt;&lt; "Hello world!\n";
    return 0;
}


Original Code

#include &lt;iostream&gt;
#include &lt;list&gt;
using namespace std;
//C++11 at least

template &lt;class baseIter&gt;
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 &amp; operator ++(void) {  baseIter::operator++();
                                        if(*this == end) baseIter::operator=(begin);
                                        return *this;}
        baseIter &amp; operator ++(int) = delete;
};

int main()
{
    list&lt;int&gt; intList = { 1, 2, 3};
    circularIterator&lt;list&lt;int&gt;::iterator&gt; circIter(intList.begin(),intList.end());

    cout &lt;&lt; *circIter &lt;&lt; endl;
    cout &lt;&lt; *(++circIter) &lt;&lt; endl;
    cout &lt;&lt; *(++circIter) &lt;&lt; endl;
    cout &lt;&lt; *(++circIter) &lt;&lt; endl;
    cout &lt;&lt; *(++circIter) &lt;&lt; endl;
    cout &lt;&lt; "..." &lt;&lt; endl;

    cout &lt;&lt; "Hello world!" &lt;&lt; endl;
    return 0;
}
High level overview:

The idea is solid, but creating an iterator adapter to make the container behave differently just sounds weird. It would be better to have container adapters, as std::stack&lt;&gt; and std::queue&lt;&gt; do.

Implementation overview:

The code has a serious issues. Mainly the following:


It has a chance to break on some algorithms:

auto second = ++first;



where first is circularIterator&lt;&gt; will make second to be baseIter.  The most dangerous ones are sorting algorithms, especially those that use divide and conquer. The template type parameter is usually only one, e.g. only one type of iterators are allowed, as a result the compiler will issue substitution failure error.


Will not work on idiomatic while (*first++ != last) or similar.


The postfix increment is deleted, thus it disables probably most of the standard library.


The class pretends to be an iterator, but is a range. 


Usually iterator should know about its own internal state only. Knowing end iterator should be last resort. Actually, the reason for storing the range is because the code doesn't provide a function to create a pair of circularIterators. If such function would be provided, the operator==() of parent iterator would still work, as they mostly take it by reference.

Cosmetics:

Not really important, but here they are:


Usually people name types (and classes, as a result) in CamelCase or snake_case. camelCase starting from regular letter are used for variable names. 
Template type parameters are named using CamelCase, since in the future they will probably become Concepts.
Indentation and brace placing is very weird.


Misc:


using namespace std; is bad. It causes name clashes and in general confuses other mechanisms of C++.
std::endl is a performance drainer. If done in a tight loop, can cause serious issues. Bjarne Stroustrup himself didn't use it for a decade.