Boost logo

Boost :

From: nbecker_at_[hidden]
Date: 2002-01-30 08:11:18


Here is a modified version of the cyclic iterator adaptor. The
iterator_adaptor member functions are really static functions, so they
must not directly access the other members. I have modified this. I
don't think the code is fully working yet, but I think this is closer
to the target:

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

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


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