| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697 | // 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_facade.hpp>#include <iterator>namespace boost{    namespace range_detail    {        // strided_iterator for wrapping a forward traversal iterator        template<class BaseIterator, class Category>        class strided_iterator            : public iterator_facade<                strided_iterator<BaseIterator, Category>                , typename iterator_value<BaseIterator>::type                , forward_traversal_tag                , typename iterator_reference<BaseIterator>::type                , typename iterator_difference<BaseIterator>::type            >        {            friend class ::boost::iterator_core_access;            typedef iterator_facade<                strided_iterator<BaseIterator, Category>                , typename iterator_value<BaseIterator>::type                , forward_traversal_tag                , typename iterator_reference<BaseIterator>::type                , typename iterator_difference<BaseIterator>::type            > super_t;        public:            typedef typename super_t::difference_type difference_type;            typedef typename super_t::reference reference;            typedef BaseIterator base_iterator;            typedef std::forward_iterator_tag iterator_category;            strided_iterator()                : m_it()                , m_last()                , m_stride()            {            }            strided_iterator(base_iterator   it,                             base_iterator   last,                             difference_type stride)                : m_it(it)                , m_last(last)                , m_stride(stride)            {            }            template<class OtherIterator>            strided_iterator(                const strided_iterator<OtherIterator, Category>& other,                typename enable_if_convertible<                    OtherIterator,                    base_iterator                >::type* = 0            )                : m_it(other.base())                , m_last(other.base_end())                , m_stride(other.get_stride())            {            }            base_iterator base() const            {                return m_it;            }            base_iterator base_end() const            {                return m_last;            }            difference_type get_stride() const            {                return m_stride;            }        private:            void increment()            {                for (difference_type i = 0;                        (m_it != m_last) && (i < m_stride); ++i)                {                    ++m_it;                }            }            reference dereference() const            {                return *m_it;            }            template<class OtherIterator>            bool equal(                const strided_iterator<OtherIterator, Category>& other,                typename enable_if_convertible<                    OtherIterator,                    base_iterator                >::type* = 0) const            {                return m_it == other.m_it;            }            base_iterator m_it;            base_iterator m_last;            difference_type m_stride;        };        // strided_iterator for wrapping a bidirectional iterator        template<class BaseIterator>        class strided_iterator<BaseIterator, bidirectional_traversal_tag>            : public iterator_facade<                strided_iterator<BaseIterator, bidirectional_traversal_tag>                , typename iterator_value<BaseIterator>::type                , bidirectional_traversal_tag                , typename iterator_reference<BaseIterator>::type                , typename iterator_difference<BaseIterator>::type            >        {            friend class ::boost::iterator_core_access;            typedef iterator_facade<                strided_iterator<BaseIterator, bidirectional_traversal_tag>                , typename iterator_value<BaseIterator>::type                , bidirectional_traversal_tag                , typename iterator_reference<BaseIterator>::type                , typename iterator_difference<BaseIterator>::type            > super_t;        public:            typedef typename super_t::difference_type difference_type;            typedef typename super_t::reference reference;            typedef BaseIterator base_iterator;            typedef typename boost::make_unsigned<difference_type>::type                        size_type;            typedef std::bidirectional_iterator_tag iterator_category;            strided_iterator()                : m_it()                , m_offset()                , m_index()                , m_stride()            {            }            strided_iterator(base_iterator   it,                             size_type       index,                             difference_type stride)                : m_it(it)                , m_offset()                , m_index(index)                , m_stride(stride)            {                if (stride && ((m_index % stride) != 0))                    m_index += (stride - (m_index % stride));            }            template<class OtherIterator>            strided_iterator(                const strided_iterator<                    OtherIterator,                    bidirectional_traversal_tag                >& other,                typename enable_if_convertible<                    OtherIterator,                    base_iterator                >::type* = 0            )                : m_it(other.base())                , m_offset(other.get_offset())                , m_index(other.get_index())                , m_stride(other.get_stride())            {            }            base_iterator base() const            {                return m_it;            }            difference_type get_offset() const            {                return m_offset;            }            size_type get_index() const            {                return m_index;            }            difference_type get_stride() const            {                return m_stride;            }        private:            void increment()            {                m_offset += m_stride;            }            void decrement()            {                m_offset -= m_stride;            }            reference dereference() const            {                update();                return *m_it;            }            void update() const            {                std::advance(m_it, m_offset);                m_index += m_offset;                m_offset = 0;            }            template<class OtherIterator>            bool equal(                const strided_iterator<                    OtherIterator,                    bidirectional_traversal_tag                >& other,                typename enable_if_convertible<                    OtherIterator,                    base_iterator                >::type* = 0) const            {                return (m_index + m_offset) ==                            (other.get_index() + other.get_offset());            }            mutable base_iterator m_it;            mutable difference_type m_offset;            mutable size_type m_index;            difference_type m_stride;        };        // strided_iterator implementation for wrapping a random access iterator        template<class BaseIterator>        class strided_iterator<BaseIterator, random_access_traversal_tag>            : public iterator_facade<                strided_iterator<BaseIterator, random_access_traversal_tag>                , typename iterator_value<BaseIterator>::type                , random_access_traversal_tag                , typename iterator_reference<BaseIterator>::type                , typename iterator_difference<BaseIterator>::type            >        {            friend class ::boost::iterator_core_access;            typedef iterator_facade<                strided_iterator<BaseIterator, random_access_traversal_tag>                , typename iterator_value<BaseIterator>::type                , random_access_traversal_tag                , typename iterator_reference<BaseIterator>::type                , typename iterator_difference<BaseIterator>::type            > super_t;        public:            typedef typename super_t::difference_type difference_type;            typedef typename super_t::reference reference;            typedef BaseIterator base_iterator;            typedef std::random_access_iterator_tag iterator_category;            strided_iterator()                : m_it()                , m_first()                , m_index(0)                , m_stride()            {            }            strided_iterator(                base_iterator   first,                base_iterator   it,                difference_type stride            )                : m_it(it)                , m_first(first)                , m_index(stride ? (it - first) : difference_type())                , m_stride(stride)            {                if (stride && ((m_index % stride) != 0))                    m_index += (stride - (m_index % stride));            }            template<class OtherIterator>            strided_iterator(                const strided_iterator<                    OtherIterator,                    random_access_traversal_tag                >& other,                typename enable_if_convertible<                    OtherIterator,                    base_iterator                >::type* = 0            )                : m_it(other.base())                , m_first(other.base_begin())                , m_index(other.get_index())                , m_stride(other.get_stride())            {            }            base_iterator base_begin() const            {                return m_first;            }            base_iterator base() const            {                return m_it;            }            difference_type get_stride() const            {                return m_stride;            }            difference_type get_index() const            {                return m_index;            }        private:            void increment()            {                m_index += m_stride;            }            void decrement()            {                m_index -= m_stride;            }            void advance(difference_type offset)            {                m_index += (m_stride * offset);            }            // Implementation detail: only update the actual underlying iterator            // at the point of dereference. This is done so that the increment            // and decrement can overshoot the valid sequence as is required            // by striding. Since we can do all comparisons just with the index            // simply, and all dereferences must be within the valid range.            void update() const            {                m_it = m_first + m_index;            }            template<class OtherIterator>            difference_type distance_to(                const strided_iterator<                    OtherIterator,                    random_access_traversal_tag                >& other,                typename enable_if_convertible<                            OtherIterator, base_iterator>::type* = 0) const            {                BOOST_ASSERT((other.m_index - m_index) % m_stride == difference_type());                return (other.m_index - m_index) / m_stride;            }            template<class OtherIterator>            bool equal(                const strided_iterator<                    OtherIterator,                    random_access_traversal_tag                >& other,                typename enable_if_convertible<                            OtherIterator, base_iterator>::type* = 0) const            {                return m_index == other.m_index;            }            reference dereference() const            {                update();                return *m_it;            }        private:            mutable base_iterator m_it;            base_iterator m_first;            difference_type m_index;            difference_type m_stride;        };        template<class Rng, class Difference> inline        strided_iterator<            typename range_iterator<Rng>::type,            forward_traversal_tag        >        make_begin_strided_iterator(            Rng& rng,            Difference stride,            forward_traversal_tag)        {            return strided_iterator<                typename range_iterator<Rng>::type,                forward_traversal_tag            >(boost::begin(rng), boost::end(rng), stride);        }        template<class Rng, class Difference> inline        strided_iterator<            typename range_iterator<const Rng>::type,            forward_traversal_tag        >        make_begin_strided_iterator(            const Rng& rng,            Difference stride,            forward_traversal_tag)        {            return strided_iterator<                typename range_iterator<const Rng>::type,                forward_traversal_tag            >(boost::begin(rng), boost::end(rng), stride);        }        template<class Rng, class Difference> inline        strided_iterator<            typename range_iterator<Rng>::type,            forward_traversal_tag        >        make_end_strided_iterator(            Rng& rng,            Difference stride,            forward_traversal_tag)        {            return strided_iterator<                typename range_iterator<Rng>::type,                forward_traversal_tag            >(boost::end(rng), boost::end(rng), stride);        }        template<class Rng, class Difference> inline        strided_iterator<            typename range_iterator<const Rng>::type,            forward_traversal_tag        >        make_end_strided_iterator(            const Rng& rng,            Difference stride,            forward_traversal_tag)        {            return strided_iterator<                typename range_iterator<const Rng>::type,                forward_traversal_tag            >(boost::end(rng), boost::end(rng), stride);        }        template<class Rng, class Difference> inline        strided_iterator<            typename range_iterator<Rng>::type,            bidirectional_traversal_tag        >        make_begin_strided_iterator(            Rng& rng,            Difference stride,            bidirectional_traversal_tag)        {            typedef typename range_difference<Rng>::type difference_type;            return strided_iterator<                typename range_iterator<Rng>::type,                bidirectional_traversal_tag            >(boost::begin(rng), difference_type(), stride);        }        template<class Rng, class Difference> inline        strided_iterator<            typename range_iterator<const Rng>::type,            bidirectional_traversal_tag        >        make_begin_strided_iterator(            const Rng& rng,            Difference stride,            bidirectional_traversal_tag)        {            typedef typename range_difference<const Rng>::type difference_type;            return strided_iterator<                typename range_iterator<const Rng>::type,                bidirectional_traversal_tag            >(boost::begin(rng), difference_type(), stride);        }        template<class Rng, class Difference> inline        strided_iterator<            typename range_iterator<Rng>::type,            bidirectional_traversal_tag        >        make_end_strided_iterator(            Rng& rng,            Difference stride,            bidirectional_traversal_tag)        {            return strided_iterator<                typename range_iterator<Rng>::type,                bidirectional_traversal_tag            >(boost::end(rng), boost::size(rng), stride);        }        template<class Rng, class Difference> inline        strided_iterator<            typename range_iterator<const Rng>::type,            bidirectional_traversal_tag        >        make_end_strided_iterator(            const Rng& rng,            Difference stride,            bidirectional_traversal_tag)        {            return strided_iterator<                typename range_iterator<const Rng>::type,                bidirectional_traversal_tag            >(boost::end(rng), boost::size(rng), stride);        }        template<class Rng, class Difference> inline        strided_iterator<            typename range_iterator<Rng>::type,            random_access_traversal_tag        >        make_begin_strided_iterator(            Rng& rng,            Difference stride,            random_access_traversal_tag)        {            return strided_iterator<                typename range_iterator<Rng>::type,                random_access_traversal_tag            >(boost::begin(rng), boost::begin(rng), stride);        }        template<class Rng, class Difference> inline        strided_iterator<            typename range_iterator<const Rng>::type,            random_access_traversal_tag        >        make_begin_strided_iterator(            const Rng& rng,            Difference stride,            random_access_traversal_tag)        {            return strided_iterator<                typename range_iterator<const Rng>::type,                random_access_traversal_tag            >(boost::begin(rng), boost::begin(rng), stride);        }        template<class Rng, class Difference> inline        strided_iterator<            typename range_iterator<Rng>::type,            random_access_traversal_tag        >        make_end_strided_iterator(            Rng& rng,            Difference stride,            random_access_traversal_tag)        {            return strided_iterator<                typename range_iterator<Rng>::type,                random_access_traversal_tag            >(boost::begin(rng), boost::end(rng), stride);        }        template<class Rng, class Difference> inline        strided_iterator<            typename range_iterator<const Rng>::type,            random_access_traversal_tag        >        make_end_strided_iterator(            const Rng& rng,            Difference stride,            random_access_traversal_tag)        {            return strided_iterator<                typename range_iterator<const Rng>::type,                random_access_traversal_tag            >(boost::begin(rng), boost::end(rng), stride);        }        template<            class Rng,            class Category =                typename iterators::pure_iterator_traversal<                    typename range_iterator<Rng>::type                >::type        >        class strided_range            : public iterator_range<                range_detail::strided_iterator<                    typename range_iterator<Rng>::type,                    Category                >            >        {            typedef range_detail::strided_iterator<                typename range_iterator<Rng>::type,                Category            > iter_type;            typedef iterator_range<iter_type> super_t;        public:            template<class Difference>            strided_range(Difference stride, Rng& rng)                : super_t(                    range_detail::make_begin_strided_iterator(                        rng, stride,                        typename iterator_traversal<                            typename range_iterator<Rng>::type                        >::type()),                    range_detail::make_end_strided_iterator(                        rng, stride,                        typename iterator_traversal<                            typename range_iterator<Rng>::type                        >::type()))            {                BOOST_ASSERT( stride >= 0 );            }        };        template<class Difference>        class strided_holder : public holder<Difference>        {        public:            explicit 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
 |