|
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