Is there a standard cyclic iterator in C++

后端 未结 6 1907
野性不改
野性不改 2020-12-13 19:30

Based on the following question: Check if one string is a rotation of other string

I was thinking of making a cyclic iterator type that takes a range, and would be a

6条回答
  •  悲哀的现实
    2020-12-13 19:55

    This should provide some ideas/solutions: 2 renditions, the second is a little lighter in weight. Both tested using a subrange of a vector and a list ...

    #include 
    
    template , typename Iterator = Container::iterator>
    class RingIterator : public std::iterator 
    {
      Container& data;
    
      Iterator   cursor;
      Iterator   begin;
      Iterator   end;
    
      public:
    
        RingIterator (Container& v) : data(v), cursor(v.begin()), begin(v.begin()), end(v.end()) {}
    
        RingIterator (Container& v, const Iterator& i) : data(v), cursor(i), begin(v.begin()), end(v.end()) {}
    
        RingIterator (Container& v, const Iterator& i, const Iterator& j) : data(v), cursor(i), begin(i), end(j) {}
    
        RingIterator (Container& v, size_t i) : data(v), cursor(v.begin() + i % v.size()), begin(v.begin()), end(v.end()) {}
    
        bool operator == (const RingIterator& x) const 
        { 
          return cursor == x.cursor; 
        }
    
        bool operator != (const RingIterator& x) const 
        {
          return ! (*this == x); 
        }
    
        reference operator*() const 
        {
          return *cursor; 
        }
    
        RingIterator& operator++() 
        {
          ++cursor;
          if (cursor == end)
            cursor = begin;
          return *this;
        }
    
        RingIterator operator++(int) 
        {
          RingIterator ring = *this;
          ++*this;
          return ring;
        }
    
        RingIterator& operator--() 
        {
          if (cursor == begin)
            cursor = end;
          --cursor;
          return *this;
        }
    
        RingIterator operator--(int) 
        {
          RingIterator ring = *this;
          --*this; 
          return ring;
        }
    
        RingIterator insert (const T& x)
        {
          return RingIterator (data, data.insert (cursor, x));
        }
    
        RingIterator erase() 
        {
          return RingIterator (data, data.erase (cursor));
        }
    };
    
    template 
    class CyclicIterator : public std::iterator 
    {
      Iterator   cursor;
      Iterator   begin;
      Iterator   end;
    
      public:
    
        CyclicIterator (const Iterator& i, const Iterator& j) : cursor(i), begin(i), end(j) {}
    
        bool operator == (const CyclicIterator& x) const 
        { 
          return cursor == x.cursor; 
        }
    
        bool operator != (const CyclicIterator& x) const 
        {
          return ! (*this == x); 
        }
    
        reference operator*() const 
        {
          return *cursor; 
        }
    
        CyclicIterator& operator++() 
        {
          ++cursor;
          if (cursor == end)
            cursor = begin;
          return *this;
        }
    
        CyclicIterator operator++(int) 
        {
          CyclicIterator ring = *this;
          ++*this;
          return ring;
        }
    
        CyclicIterator& operator--() 
        {
          if (cursor == begin)
            cursor = end;
          --cursor;
          return *this;
        }
    
        CyclicIterator operator--(int) 
        {
          CyclicIterator ring = *this;
          --*this; 
          return ring;
        }
    };
    
    #include 
    #include 
    
    #include 
    
    enum { CycleSize = 9, ContainerSize };
    
    template 
    void test (cyclicIterator& iterator, size_t mn)
    {
      int m = mn;
      while (m--)
        for (int n = mn; n--; ++iterator)
          std::cout << std::setw(3) << *iterator << ' ';
      --iterator;
      m = mn;
      while (m--)
        for (int n = mn; n--; --iterator)
          std::cout << std::setw(3) << *iterator << ' ';
    }
    
    template 
    void load (containers& container)
    {
      while (container.size() < ContainerSize)
        container.push_back (container.size());
    }
    
    void main (void)
    {
      typedef std::vector     vContainer;
      typedef vContainer::iterator vIterator;
      typedef std::list       lContainer;
      typedef lContainer::iterator lIterator;
    
      vContainer v;  load (v);
      vIterator vbegin = v.begin() + 1;
    
      RingIterator  vring (v, vbegin, v.end());
      CyclicIterator  vcycle (vbegin, v.end());
    
      lContainer l;  load (l);
      lIterator lbegin = l.begin(); ++lbegin;
    
      RingIterator  lring (l, lbegin, l.end());
      CyclicIterator  lcycle (lbegin, l.end());
    
      test (vring, CycleSize);
      test (vcycle, CycleSize);
      test (lring, CycleSize);
      test (lcycle, CycleSize);
    }
    

提交回复
热议问题