我想实现一个基于std::list的循环列表。我想从列表的优点中获益,但是添加了一个特定的特性:它的迭代器操作符++和--应该跳过边缘,并且操作(插入/擦除)不能使现有的迭代器无效。我在处理模板方面的技能很弱,理解std容器对我来说是不可能的。所以我需要你的帮助。到目前为止,我并没有那么远:D.抱歉,即使是众多的帖子也对我没有进一步的帮助。
受你们的启发,我现在可以发布我上一次所做的……大约12个小时:D基本上是你建议的,但是有很好的小运算符。
#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;
};发布于 2012-10-14 20:46:41
你就不能做一个不同的迭代器类型吗?
#include <iterator>
#include <list>
template <typename T, typename Alloc>
struct cyclic_iterator
: std::iterator<typename std::list<T, Alloc>::iterator::iterator_category, T>
{
typedef std::list<T, Alloc> list_type;
cyclic_iterator & operator++()
{
++iter;
if (iter == container.end()) { iter = container.begin(); }
return *this;
}
T & operator*() { return *iter; }
cyclic_iterator(typename list_type::iterator it, list_type & l)
: iter(it)
, container(l)
{
if (it == container.end()) { it = container.begin(); }
}
// everything else
private:
typename list_type::iterator iter;
list_type & container;
};使用帮助器:
template <typename List>
cyclic_iterator<typename List::value_type, typename List::allocator_type>
make_cyclic_iterator(typename List::iterator it, List & l)
{
return cyclic_iterator<typename List::value_type, typename List::allocator_type>(it, l);
}用法:
// goes round and round forever
for (auto ci = make_cyclic_iterator(mylist.begin(), mylist); ; ++ci)
{
std::cout << *ci << std::endl;
}(只需稍加修改,就可以使此代码在任何公开begin/end迭代器的容器上工作。)
发布于 2012-10-14 20:19:35
这不可能。迭代器和end元素的实现是特定于实现的,不能自定义。容器不是为这种事情设计的,这会使它们变得非常困难。你将不得不自己经历实现这一点的痛苦。请记住,这会变得非常棘手,因为循环列表没有真正的过端迭代器,迭代器也不能真正处理这种情况。一些库有一个Circulator概念来处理循环结构。
注意:从标准容器继承不是一个好主意。
发布于 2012-10-14 20:52:45
当然,您可以使用std::list实现它,但首先您应该将list封装在您的类中,而不是从它派生;其次,您必须实现您自己的迭代器来完成此任务,但是由于循环列表的大小是固定的,因此我更喜欢使用具有固定大小和线性内存的容器,如std::array或std::vector。
template<
class T,
class Container = std::vector<T>
>
class circular_list {
public:
// Following typedef are required to make your class a container
typedef typename Container::size_type size_type;
typedef typename Container::difference_type difference_type;
typedef typename Container::pointer pointer;
typedef typename Container::const_pointer const_pointer;
typedef typename Container::reference reference;
typedef typename Container::const_reference const_reference;
typedef typename Container::value_type value_type;
public:
class iterator : std::iterator<std::bidirectional_iterator_tag, value_type> {
public:
iterator() : c_(nullptr) {}
iterator(circular_buffer& c, size_type index)
: c_( &c.c_ ), index_( index ) {}
reference operator* () const {
return (*c_)[index_];
}
iterator& operator++ () {
if( ++index_ >= c_->size() ) index_ = 0;
return *this;
}
iterator& operator-- () {
if( index_ == 0 ) index_ = c_->size() - 1; else --index_;
return *this;
}
private:
size_type index_;
Container* c_;
};
public:
void push( const_reference val ) {add item to the container}
reference current() {return current item from the container}
void pop() {remove item from the container}
size_type size() const {return c_.size();}
iterator begin() {return iterator( *this, 0 );}
iterator end() {return iterator( *this, size() );}
private:
friend iterator;
Container c_;
}https://stackoverflow.com/questions/12882090
复制相似问题