I want to implement a cyclic list based on std::list. I want to profit from the benfits of the list but add one specific feature: its iterator operators ++ and — should hop over the edges and operations (insert/erase) must not invalidate existing iterators. My skills in handling templates are weak and to understand the std containers is an impossible act for me. Hence i need your help. By now im not that far :D. Sorry but even the numerous posts dont help me any further.
EDIT:
Well after a lot of work, a steeeep learnig curve, the failed approach to inherit from std::list::iterator, a short-term depression and a abasing return to your approaches (yes, you all were right) I finally made it. Inspired by all your contibutions, I can now post what I did the last … about 12 hours 😀 Basicly what you suggested, but with nice little operators.
#pragma once
#include <list>
using std::list;
template<class T>
class cyclic_iterator;
template<class T>
class cyclicList : public list<T>
{
public:
typedef cyclic_iterator<T> cyclic_iterator;
cyclic_iterator cycbegin()
{// not the purpose, but needed for instanziation
return cyclic_iterator( *this, this->begin());
}
cyclic_iterator cycend()
{// not the purpose, but needed for instanziation
return cyclic_iterator( *this, this->end());
}
};
template<class T>
class cyclic_iterator
{
public:
// To hop over edges need to know the container
cyclic_iterator(){}
cyclic_iterator(typename list<T>::iterator i)
: mIter(i){}
cyclic_iterator(list<T> &c)
: mContainer(&c){}
cyclic_iterator(list<T> &c, typename list<T>::iterator i)
: mContainer(&c), mIter(i){}
cyclic_iterator<T>& operator=(typename list<T>::iterator i)
{// assign an interator
mIter = i;
return *this;
}
cyclic_iterator<T>& operator=(list<T> &c)
{// assign a container
mContainer = &c;
return *this;
}
bool operator==(const cyclic_iterator<T>& rVal) const
{// check for equality
return (this->mIter == rVal.mIter && this->mContainer == rVal.mContainer) ? true : false;
}
bool operator!=(const cyclic_iterator<T>& rVal) const
{// check for inequality
return !(this->operator==(rVal));
}
cyclic_iterator<T>& operator++()
{// preincrement
++mIter;
if (mIter == mContainer->end())
{ mIter = mContainer->begin(); }
return *this;
}
cyclic_iterator<T> operator++(int)
{ // postincrement
cyclic_iterator<T> tmp = *this;
++*this;
return tmp;
}
cyclic_iterator<T>& operator--()
{// predecrement
if (mIter == mContainer->begin())
mIter = --mContainer->end();
else --mIter;
return *this;
}
cyclic_iterator<T> operator--(int)
{// postdecrement
cyclic_iterator<T> tmp = *this;
--*this;
return tmp;
}
cyclic_iterator<T>& operator+=(int j)
{// hop j nodes forward
for (int i = 0; i < j; ++i)
++(*this);
return *this;
}
cyclic_iterator<T>& operator-=(int j)
{// hop j nodes backwards
for (int i = 0; i < j; ++i)
--(*this);
return *this;
}
T& operator*()
{
return *mIter;
}
typename list<T>::iterator & getStdIterator()
{
return mIter;
}
private:
list<T>* mContainer;
typename list<T>::iterator mIter;
};
Can’t you just make a different iterator type?
With a helper:
Usage:
(With a few modifications, this code could be made to work on any container that exposes
begin/enditerators.)