Boost logo

Boost :

From: Neal D. Becker (nbecker_at_[hidden])
Date: 2002-10-01 09:23:08


This is from Gennadiy Rozental. I believe this is the latest
version. Please correct me if not. Since it is small, I'll just post it here:

// (C) Copyright Gennadiy Rozental 2002.
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
//
// See http://www.boost.org for most recent version including documentation.

#ifndef CYCLE_ITERATOR_HPP
#define CYCLE_ITERATOR_HPP

#include<boost/iterator_adaptors.hpp>

#include<utility>

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( BaseIterator const& b, BaseIterator const& e )
    : m_bounds( b, e ) {}

    // policy implementation
    template<typename CycleIterator>
    void increment( CycleIterator& x ) const
    {
        if( m_bounds.first == m_bounds.second )
            return;

        if( ++x.base() == m_bounds.second )
            x.base() = m_bounds.first;
    }

    template<typename CycleIterator>
    void decrement( CycleIterator& x ) const
    {
        if( m_bounds.first == m_bounds.second )
            return;

        if( x.base() == m_bounds.first )
            x.base() = m_bounds.second;

        --x.base();
    }

    template <typename CycleIterator>
    void advance( CycleIterator& x, difference_type n ) const
    {
        const difference_type cycle_size = m_bounds.second - m_bounds.first;
        
        if( cycle_size == 0 )
            return;

        n %= cycle_size;

        x.base() = m_bounds.first + ( x.base() - m_bounds.first + n + cycle_size ) % cycle_size;
    }

    template <class CycleIterator1, class CycleIterator2>
    difference_type
    distance(const CycleIterator1& x, const CycleIterator2& y) const
    {
        const difference_type cycle_size = m_bounds.second - m_bounds.first;
        
        if( cycle_size == 0 )
            return 0;

        return (y.base() - x.base() + cycle_size) % cycle_size;
    }

private:
    // Data members
    const std::pair<BaseIterator,BaseIterator> m_bounds;
};

} // namespace detail

template<typename BaseIterator,
         typename Value = boost::detail::iterator_traits<BaseIterator>::value_type
>
struct cycle_iterator_generator {
    typedef detail::cycle_iterator_policy<BaseIterator> policies_type;
    typedef boost::iterator_adaptor<BaseIterator,policies_type,Value> type;
};

template<typename BaseIterator, typename ConstBaseIterator,
         typename Value = boost::detail::iterator_traits<BaseIterator>::value_type,
         typename ConstValue = boost::detail::iterator_traits<ConstBaseIterator>::value_type
>
struct cycle_iterator_pair_generator
{
    typedef detail::cycle_iterator_policy<BaseIterator> policies_type;
    typedef boost::iterator_adaptor<BaseIterator,policies_type,Value> iterator;
    typedef boost::iterator_adaptor<ConstBaseIterator,policies_type,ConstValue> const_iterator;

};

#ifndef __SUNPRO_CC
template<typename BaseIterator>
typename cycle_iterator_generator<BaseIterator>::type
make_cycle_iterator( BaseIterator const& base, std::pair<BaseIterator, BaseIterator> const& range) {
    typedef typename cycle_iterator_generator<BaseIterator>::type ret_type;

    return ret_type( base,
                     detail::cycle_iterator_policy<BaseIterator>( range.first, range.second ) );
}

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

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

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

} // namespace boost

#endif

// Revision History
// 29 Jan 02 Initial version (Gennadiy Rozental)
// 3 Feb 02 Eliminate raising of iterator category (Gennadiy Rozental;Thanks to Thomas Witt)
// 3 Feb 02 Added cycle_iterator_pair_generator (Gennadiy Rozental;Thanks to Thomas Witt for poining out interoperability issue)
// 4 Feb 02 Added distance implementation (Gennadiy Rozental;Thanks to Neal Becker for pointing out need for it)
// 17 Feb 02 Removed <algorithm> include (Thomas Witt)
// 17 Feb 02 Added const qualifiers (Thomas Witt)
// 17 Feb 02 Made iterator parameters const& (Thomas Witt)
// 17 Feb 02 Added make_cycle_iterator with base parameter (Thomas Witt)


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