Boost logo

Boost :

From: nbecker_at_[hidden]
Date: 2002-01-29 14:56:32


Interesting. Here's what I came up with. So far, it is an iterator
adaptor, that adapts a container's iterator. Typically, the container
would be vector or plain old array.

#include <boost/iterator_adaptors.hpp>
using namespace boost;

struct circ_iterator_policies : public default_iterator_policies {
  circ_iterator_policies (int _size, int _offset = 0) :
    size (_size), offset (_offset) {}

  template <class IteratorAdaptor>
  typename IteratorAdaptor::reference
  dereference(const IteratorAdaptor& iter) const
  { return *(iter.base() + iter.policies().index (offset)); }

  template <class IteratorAdaptor>
  void increment(IteratorAdaptor& x)
  { ++x.policies().offset; }

  template <class IteratorAdaptor>
  void decrement(IteratorAdaptor& x)
  { --x.policies().offset; }

  template <class IteratorAdaptor, class DifferenceType>
  void advance(IteratorAdaptor& x, DifferenceType n)
  { x.policies().offset += n; }

  template <class IteratorAdaptor1, class IteratorAdaptor2>
  typename IteratorAdaptor1::difference_type
  distance(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
  {
    typedef typename IteratorAdaptor1::difference_type ret_t;
    ret_t ret = (y.base() + y.policies().offset) - (x.base() + x.policies().offset);
    if (ret < 0)
      ret += x.policies().size;
    return ret;
  }

  template <class IteratorAdaptor1, class IteratorAdaptor2>
  bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
  { return x.base() + x.policies().index (x.policies().offset) ==
      y.base() + y.policies().index (y.policies().offset); }

  int size;
  int offset;

  int index (int offset) const {
    int x = (offset) % int(size);
    if (x >= 0)
      return x;
    else
      return x + size;
  }
};

template<typename Iterator>
struct circ_iterator_generator {
  typedef typename Iterator::value_type value_t;
  typedef iterator_adaptor<
    Iterator,
    circ_iterator_policies,
    value_t, value_t&, value_t*, std::random_access_iterator_tag>
  type;
};

template <typename Iterator>
typename circ_iterator_generator<Iterator>::type
make_circ_iterator(Iterator i, int size, int offset)
{
  typedef typename circ_iterator_generator<Iterator>::type result_t;
  return result_t (i, circ_iterator_policies (size, offset));
}

Here's a test:
#include "fifo.H"
#include <vector>
#include <iostream>

int main () {
  const int size = 10;
  std::vector<int> v (size+1);
  for (int i = 0; i < v.size(); i++)
    v[i] = i;

  std::cout << "make_circ_iterator (v.begin(), size, 2)-make_circ_iterator (v.begin(), size, 1)=" << make_circ_iterator (v.begin(), size, 2) - make_circ_iterator (v.begin(), size, 1) << '\n'
            << "make_circ_iterator (v.begin(), size, 1)-make_circ_iterator (v.begin(), size, 2)=" << make_circ_iterator (v.begin(), size, 1) - make_circ_iterator (v.begin(), size, 2) << '\n';
  std::copy (make_circ_iterator (v.begin(), size, 2), make_circ_iterator (v.begin(), size, 1), std::ostream_iterator<int> (std::cout, "\n"));
}


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk