strided.hpp 4.99 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
// Boost.Range library
//
//  Copyright Neil Groves 2007. Use, modification and
//  distribution is subject to the Boost Software License, Version
//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//
//
// For more information, see http://www.boost.org/libs/range/
//
#ifndef BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED
#define BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED

#include <boost/range/adaptor/argument_fwd.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <iterator>

namespace boost
{
    namespace range_detail
    {

        template<typename BaseIterator>
        class strided_iterator
            : public iterator_adaptor<
                        strided_iterator<BaseIterator>,
                        BaseIterator>
        {
            friend class iterator_core_access;

            typedef iterator_adaptor<strided_iterator<BaseIterator>, BaseIterator> super_t;
        
        public:
            typedef BOOST_DEDUCED_TYPENAME std::iterator_traits<BaseIterator>::difference_type          difference_type;
                
            strided_iterator() : m_stride() { }
        
            strided_iterator(const strided_iterator& other)
                : super_t(other), m_stride(other.m_stride) { }
        
            explicit strided_iterator(BaseIterator base_it, difference_type stride)
                : super_t(base_it), m_stride(stride) { }
        
            strided_iterator&
            operator=(const strided_iterator& other)
            {
                super_t::operator=(other);
            
                // Is the interoperation of the stride safe?
                m_stride = other.m_stride;
                return *this;
            }
        
            void increment() { std::advance(this->base_reference(), m_stride); }
        
            void decrement() { std::advance(this->base_reference(), -m_stride); }
        
            void advance(difference_type n) { std::advance(this->base_reference(), n * m_stride); }
        
            difference_type
            distance_to(const strided_iterator& other) const
            {
                return std::distance(this->base_reference(), other.base_reference()) / m_stride;
            }

            // Using the compiler generated copy constructor and
            // and assignment operator
        
        private:
            difference_type m_stride;
        };
    
        template<class BaseIterator> inline
        strided_iterator<BaseIterator>
        make_strided_iterator(
            const BaseIterator& first,
            BOOST_DEDUCED_TYPENAME std::iterator_traits<BaseIterator>::difference_type stride)
        {
            return strided_iterator<BaseIterator>(first, stride);
        }

        template< class Rng >
        class strided_range
            : public iterator_range<range_detail::strided_iterator<BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type> >
        {
            typedef range_detail::strided_iterator<BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type> iter_type;
            typedef iterator_range<iter_type> super_t;
        public:
            template< typename Difference >
            strided_range(Difference stride, Rng& rng)
                : super_t(make_strided_iterator(boost::begin(rng), stride),
                    make_strided_iterator(boost::end(rng), stride))
            {
            }
        };

        template<class Difference>
        class strided_holder : public holder<Difference>
        {
        public:
            strided_holder(Difference value) : holder<Difference>(value) {}
        };

        template<class Rng, class Difference>
        inline strided_range<Rng>
        operator|(Rng& rng, const strided_holder<Difference>& stride)
        {
            return strided_range<Rng>(stride.val, rng);
        }

        template<class Rng, class Difference>
        inline strided_range<const Rng>
        operator|(const Rng& rng, const strided_holder<Difference>& stride)
        {
            return strided_range<const Rng>(stride.val, rng);
        }

    } // namespace range_detail
    
    using range_detail::strided_range;

    namespace adaptors
    {
    
        namespace
        {
            const range_detail::forwarder<range_detail::strided_holder>
                strided = range_detail::forwarder<range_detail::strided_holder>();
        }
        
        template<class Range, class Difference>
        inline strided_range<Range>
        stride(Range& rng, Difference step)
        {
            return strided_range<Range>(step, rng);
        }
        
        template<class Range, class Difference>
        inline strided_range<const Range>
        stride(const Range& rng, Difference step)
        {
            return strided_range<const Range>(step, rng);
        }
        
    } // namespace 'adaptors'
} // namespace 'boost'

#endif