Boost logo

Boost :

From: nbecker_at_[hidden]
Date: 2002-01-30 08:46:20


>>>>> "David" == David Abrahams <david.abrahams_at_[hidden]> writes:

    David> FWIW: The policy functions don't have to be static functions. You can store
    David> state in the policies and access it directly.

Sorry, my mistake. I did find the problem with the cyclic_iterator
though. It needed distance defined so that things like std::copy
would work correctly. Here is a version which may be working:

#ifndef CYCLE_ITERATOR_HPP
#define CYCLE_ITERATOR_HPP

#include<boost/iterator_adaptors.hpp>

#include<utility>
#include<algorithm>

namespace boost {

namespace detail{

template<typename BaseIterator>
class cycle_iterator_policy : public default_iterator_policies {
    typedef boost::detail::iterator_traits<BaseIterator>::difference_type difference_type;
public:
    // Constructors
        cycle_iterator_policy() {}
    cycle_iterator_policy( BaseIterator const& b, BaseIterator const& e, difference_type cycle_size )
    : m_bounds( b, e ), m_cycle_size( cycle_size ) {}
// cycle_iterator_policy( cycle_iterator_policy const& other )
// : m_bounds( other.m_bounds ), m_cycle_size( other.m_cycle_size ) {}

    // policy implementation
    template<typename CycleIterator>
    static void increment( CycleIterator& x ) {
        if( x.policies().m_bounds.first == x.policies().m_bounds.second )
            return;
        if( ++x.base() == x.policies().m_bounds.second )
            x.base() = x.policies().m_bounds.first;
    }

    template<typename CycleIterator>
    static void decrement( CycleIterator& x ) {
        if( x.policies().m_bounds.first == x.policies().m_bounds.second )
            return;
        if( x.base() == x.policies().m_bounds.first ) {
            x.base() = x.policies().m_bounds.second;
        }
        --x.base();
    }

    template <typename CycleIterator>
    static void advance( CycleIterator& x, difference_type n ) {
        n %= x.policies().m_cycle_size;

        advance_impl( x, n, CycleIterator::iterator_category );
    }

  template<typename CycleIterator1, typename CycleIterator2>
  typename CycleIterator1::difference_type
  distance(const CycleIterator1& x, const CycleIterator2& y) const
  {
    typedef typename CycleIterator1::difference_type ret_t;
    ret_t ret = y.base() - x.base();
    if (ret < 0)
      ret += x.policies().m_cycle_size;
    return ret;
  }

private:

  template<typename CycleIterator> static void advance_impl( CycleIterator& x, difference_type n, std::forward_iterator_tag )
    {
        n += x.policies().m_cycle_size;
        n %= x.policies().m_cycle_size;

        while( n-- != 0 )
            increment( x );
    }
    
    template<typename CycleIterator> static void advance_impl( CycleIterator& x, difference_type n, std::bidirectional_iterator_tag )
    {
        if( n > 0 ) {
            if( n > x.policies().m_cycle_size/2 ) {
                n -= x.policies().m_cycle_size;
            }
            else {
                while( n-- != 0 )
                    increment( x );

                return;
            }
        }

        while( n++ != 0 )
            decrement( x );
    }
    template<typename CycleIterator> static void advance_impl( CycleIterator& x, difference_type n, std::random_access_iterator_tag )
    {
      x.base() = x.policies().m_bounds.first + ( x.base() - x.policies().m_bounds.first + n + x.policies().m_cycle_size ) % x.policies().m_cycle_size;
    }

    // Data members
    std::pair<BaseIterator,BaseIterator> m_bounds;
    difference_type m_cycle_size;
};

} // namespace detail

template<typename BaseIterator>
struct cycle_iterator_generator {
    typedef boost::iterator_adaptor<BaseIterator,detail::cycle_iterator_policy<BaseIterator> > type;
};

#ifndef __SUNPRO_CC
template<typename BaseIterator>
typename cycle_iterator_generator<BaseIterator>::type
make_cycle_iterator( BaseIterator const& begin, BaseIterator const& end ) {
    typedef typename cycle_iterator_generator<BaseIterator>::type ret_type;

    return ret_type( begin, detail::cycle_iterator_policy<BaseIterator>( begin, end, boost::detail::distance( begin, end ) ) );
}

template<typename BaseIterator, class Container>
typename cycle_iterator_generator<BaseIterator>::type
make_cycle_iterator( Container const& c ) {
    typedef typename cycle_iterator_generator<BaseIterator>::type ret_type;

    return ret_type( c.begin(), detail::cycle_iterator_policy<BaseIterator>( c.begin(), c.end(), c.size() ) );
}
#endif
    
} // namespace boost

#endif

Test:

#include "cyclic_iterator.hpp"
#include <vector>
#include <iostream>

int main () {
  std::vector<int> v (10);
  for (int i = 0; i < 10; i++)
    v[i] = i;
  typedef boost::cycle_iterator_generator<std::vector<int>::iterator>::type type;

  type i = boost::make_cycle_iterator (v.begin(), v.end());
  type j = i + 2;

  // std::copy (boost::make_cycle_iterator (v.begin(), v.end()), boost::make_cycle_iterator (v.begin(), v.end()) + 2, std::ostream_iterator<int> (std::cout, "\n"));
  std::copy (boost::make_cycle_iterator (v.begin(), v.end()) + 2, boost::make_cycle_iterator (v.begin(), v.end()), 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