1 | // Boost.Range library |
---|
2 | // |
---|
3 | // Copyright Neil Groves 2007. Use, modification and |
---|
4 | // distribution is subject to the Boost Software License, Version |
---|
5 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
---|
6 | // http://www.boost.org/LICENSE_1_0.txt) |
---|
7 | // |
---|
8 | // |
---|
9 | // For more information, see http://www.boost.org/libs/range/ |
---|
10 | // |
---|
11 | #ifndef BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED |
---|
12 | #define BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED |
---|
13 | |
---|
14 | #include <boost/range/adaptor/argument_fwd.hpp> |
---|
15 | #include <boost/range/iterator_range.hpp> |
---|
16 | #include <boost/iterator/iterator_adaptor.hpp> |
---|
17 | #include <iterator> |
---|
18 | |
---|
19 | namespace boost |
---|
20 | { |
---|
21 | namespace range_detail |
---|
22 | { |
---|
23 | |
---|
24 | template<typename BaseIterator> |
---|
25 | class strided_iterator |
---|
26 | : public iterator_adaptor< |
---|
27 | strided_iterator<BaseIterator>, |
---|
28 | BaseIterator> |
---|
29 | { |
---|
30 | friend class iterator_core_access; |
---|
31 | |
---|
32 | typedef iterator_adaptor<strided_iterator<BaseIterator>, BaseIterator> super_t; |
---|
33 | |
---|
34 | public: |
---|
35 | typedef BOOST_DEDUCED_TYPENAME std::iterator_traits<BaseIterator>::difference_type difference_type; |
---|
36 | |
---|
37 | strided_iterator() : m_stride() { } |
---|
38 | |
---|
39 | strided_iterator(const strided_iterator& other) |
---|
40 | : super_t(other), m_stride(other.m_stride) { } |
---|
41 | |
---|
42 | explicit strided_iterator(BaseIterator base_it, difference_type stride) |
---|
43 | : super_t(base_it), m_stride(stride) { } |
---|
44 | |
---|
45 | strided_iterator& |
---|
46 | operator=(const strided_iterator& other) |
---|
47 | { |
---|
48 | super_t::operator=(other); |
---|
49 | |
---|
50 | // Is the interoperation of the stride safe? |
---|
51 | m_stride = other.m_stride; |
---|
52 | return *this; |
---|
53 | } |
---|
54 | |
---|
55 | void increment() { std::advance(this->base_reference(), m_stride); } |
---|
56 | |
---|
57 | void decrement() { std::advance(this->base_reference(), -m_stride); } |
---|
58 | |
---|
59 | void advance(difference_type n) { std::advance(this->base_reference(), n * m_stride); } |
---|
60 | |
---|
61 | difference_type |
---|
62 | distance_to(const strided_iterator& other) const |
---|
63 | { |
---|
64 | return std::distance(this->base_reference(), other.base_reference()) / m_stride; |
---|
65 | } |
---|
66 | |
---|
67 | // Using the compiler generated copy constructor and |
---|
68 | // and assignment operator |
---|
69 | |
---|
70 | private: |
---|
71 | difference_type m_stride; |
---|
72 | }; |
---|
73 | |
---|
74 | template<class BaseIterator> inline |
---|
75 | strided_iterator<BaseIterator> |
---|
76 | make_strided_iterator( |
---|
77 | const BaseIterator& first, |
---|
78 | BOOST_DEDUCED_TYPENAME std::iterator_traits<BaseIterator>::difference_type stride) |
---|
79 | { |
---|
80 | return strided_iterator<BaseIterator>(first, stride); |
---|
81 | } |
---|
82 | |
---|
83 | template< class Rng > |
---|
84 | class strided_range |
---|
85 | : public iterator_range<range_detail::strided_iterator<BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type> > |
---|
86 | { |
---|
87 | typedef range_detail::strided_iterator<BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type> iter_type; |
---|
88 | typedef iterator_range<iter_type> super_t; |
---|
89 | public: |
---|
90 | template< typename Difference > |
---|
91 | strided_range(Difference stride, Rng& rng) |
---|
92 | : super_t(make_strided_iterator(boost::begin(rng), stride), |
---|
93 | make_strided_iterator(boost::end(rng), stride)) |
---|
94 | { |
---|
95 | } |
---|
96 | }; |
---|
97 | |
---|
98 | template<class Difference> |
---|
99 | class strided_holder : public holder<Difference> |
---|
100 | { |
---|
101 | public: |
---|
102 | strided_holder(Difference value) : holder<Difference>(value) {} |
---|
103 | }; |
---|
104 | |
---|
105 | template<class Rng, class Difference> |
---|
106 | inline strided_range<Rng> |
---|
107 | operator|(Rng& rng, const strided_holder<Difference>& stride) |
---|
108 | { |
---|
109 | return strided_range<Rng>(stride.val, rng); |
---|
110 | } |
---|
111 | |
---|
112 | template<class Rng, class Difference> |
---|
113 | inline strided_range<const Rng> |
---|
114 | operator|(const Rng& rng, const strided_holder<Difference>& stride) |
---|
115 | { |
---|
116 | return strided_range<const Rng>(stride.val, rng); |
---|
117 | } |
---|
118 | |
---|
119 | } // namespace range_detail |
---|
120 | |
---|
121 | using range_detail::strided_range; |
---|
122 | |
---|
123 | namespace adaptors |
---|
124 | { |
---|
125 | |
---|
126 | namespace |
---|
127 | { |
---|
128 | const range_detail::forwarder<range_detail::strided_holder> |
---|
129 | strided = range_detail::forwarder<range_detail::strided_holder>(); |
---|
130 | } |
---|
131 | |
---|
132 | template<class Range, class Difference> |
---|
133 | inline strided_range<Range> |
---|
134 | stride(Range& rng, Difference step) |
---|
135 | { |
---|
136 | return strided_range<Range>(step, rng); |
---|
137 | } |
---|
138 | |
---|
139 | template<class Range, class Difference> |
---|
140 | inline strided_range<const Range> |
---|
141 | stride(const Range& rng, Difference step) |
---|
142 | { |
---|
143 | return strided_range<const Range>(step, rng); |
---|
144 | } |
---|
145 | |
---|
146 | } // namespace 'adaptors' |
---|
147 | } // namespace 'boost' |
---|
148 | |
---|
149 | #endif |
---|