|
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