1

std::list に基づいて循環リストを実装したいと考えています。リストの利点から利益を得たいのですが、特定の機能を 1 つ追加します。反復子演算子 ++ および -- はエッジを飛び越える必要があり、操作 (挿入/消去) は既存の反復子を無効にしてはなりません。テンプレートを扱う私のスキルは弱く、std コンテナーを理解することは私にとって不可能な行為です。したがって、私はあなたの助けが必要です。今のところ、それほど遠くありません:D. 申し訳ありませんが、多数の投稿でさえ、これ以上役に立ちません。

編集:多くの作業の後、急な学習曲線、std::list::iterator から継承する失敗したアプローチ、短期的なうつ病、およびアプローチへの復帰 (はい、あなたはすべて正しかった) 私は最終的にやった。あなたのすべての貢献に触発されて、私が最後にしたことを投稿できるようになりました...約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;

};
4

3 に答える 3

5

別のイテレータ型を作成することはできませんか?

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

(いくつかの変更を加えることで、このコードは、 /イテレーターを公開するすべてのコンテナーで機能するように作成できます。)beginend

于 2012-10-14T12:46:40.973 に答える
3

不可能です。イテレータと end 要素の実装は実装固有であり、カスタマイズできません。コンテナはそのようなことのために設計されたものではなく、非常に難しくなります。これを自分で実装するという苦痛を経験する必要があります。循環リストには実際の最後の反復子がなく、反復子はそのような状況を実際に処理できないため、これは非常に注意が必要です。一部のライブラリには、循環構造を処理するための Circulator の概念があります。

注意: 標準コンテナから継承するのは悪い考えです。

于 2012-10-14T12:19:35.470 に答える
1

もちろん、を使用して実装できますがstd::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_;
}
于 2012-10-14T12:52:45.043 に答える