Chris@16
|
1 // Boost.Range library
|
Chris@16
|
2 //
|
Chris@16
|
3 // Copyright Neil Groves 2007. Use, modification and
|
Chris@16
|
4 // distribution is subject to the Boost Software License, Version
|
Chris@16
|
5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
6 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
7 //
|
Chris@16
|
8 //
|
Chris@16
|
9 // For more information, see http://www.boost.org/libs/range/
|
Chris@16
|
10 //
|
Chris@16
|
11 #ifndef BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED
|
Chris@16
|
12 #define BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED
|
Chris@16
|
13
|
Chris@16
|
14 #include <boost/range/adaptor/argument_fwd.hpp>
|
Chris@16
|
15 #include <boost/range/iterator_range.hpp>
|
Chris@101
|
16 #include <boost/iterator/iterator_facade.hpp>
|
Chris@16
|
17 #include <iterator>
|
Chris@16
|
18
|
Chris@16
|
19 namespace boost
|
Chris@16
|
20 {
|
Chris@16
|
21 namespace range_detail
|
Chris@16
|
22 {
|
Chris@16
|
23 // strided_iterator for wrapping a forward traversal iterator
|
Chris@16
|
24 template<class BaseIterator, class Category>
|
Chris@16
|
25 class strided_iterator
|
Chris@101
|
26 : public iterator_facade<
|
Chris@16
|
27 strided_iterator<BaseIterator, Category>
|
Chris@101
|
28 , typename iterator_value<BaseIterator>::type
|
Chris@101
|
29 , forward_traversal_tag
|
Chris@101
|
30 , typename iterator_reference<BaseIterator>::type
|
Chris@101
|
31 , typename iterator_difference<BaseIterator>::type
|
Chris@16
|
32 >
|
Chris@16
|
33 {
|
Chris@16
|
34 friend class ::boost::iterator_core_access;
|
Chris@16
|
35
|
Chris@101
|
36 typedef iterator_facade<
|
Chris@101
|
37 strided_iterator<BaseIterator, Category>
|
Chris@101
|
38 , typename iterator_value<BaseIterator>::type
|
Chris@101
|
39 , forward_traversal_tag
|
Chris@101
|
40 , typename iterator_reference<BaseIterator>::type
|
Chris@101
|
41 , typename iterator_difference<BaseIterator>::type
|
Chris@101
|
42 > super_t;
|
Chris@16
|
43
|
Chris@16
|
44 public:
|
Chris@101
|
45 typedef typename super_t::difference_type difference_type;
|
Chris@101
|
46 typedef typename super_t::reference reference;
|
Chris@16
|
47 typedef BaseIterator base_iterator;
|
Chris@101
|
48 typedef std::forward_iterator_tag iterator_category;
|
Chris@16
|
49
|
Chris@16
|
50 strided_iterator()
|
Chris@101
|
51 : m_it()
|
Chris@101
|
52 , m_last()
|
Chris@16
|
53 , m_stride()
|
Chris@16
|
54 {
|
Chris@16
|
55 }
|
Chris@16
|
56
|
Chris@101
|
57 strided_iterator(base_iterator it,
|
Chris@101
|
58 base_iterator last,
|
Chris@101
|
59 difference_type stride)
|
Chris@101
|
60 : m_it(it)
|
Chris@16
|
61 , m_last(last)
|
Chris@16
|
62 , m_stride(stride)
|
Chris@16
|
63 {
|
Chris@16
|
64 }
|
Chris@16
|
65
|
Chris@16
|
66 template<class OtherIterator>
|
Chris@101
|
67 strided_iterator(
|
Chris@101
|
68 const strided_iterator<OtherIterator, Category>& other,
|
Chris@101
|
69 typename enable_if_convertible<
|
Chris@101
|
70 OtherIterator,
|
Chris@101
|
71 base_iterator
|
Chris@101
|
72 >::type* = 0
|
Chris@101
|
73 )
|
Chris@101
|
74 : m_it(other.base())
|
Chris@16
|
75 , m_last(other.base_end())
|
Chris@16
|
76 , m_stride(other.get_stride())
|
Chris@16
|
77 {
|
Chris@16
|
78 }
|
Chris@16
|
79
|
Chris@101
|
80 base_iterator base() const
|
Chris@101
|
81 {
|
Chris@101
|
82 return m_it;
|
Chris@101
|
83 }
|
Chris@101
|
84
|
Chris@101
|
85 base_iterator base_end() const
|
Chris@101
|
86 {
|
Chris@101
|
87 return m_last;
|
Chris@101
|
88 }
|
Chris@101
|
89
|
Chris@101
|
90 difference_type get_stride() const
|
Chris@101
|
91 {
|
Chris@101
|
92 return m_stride;
|
Chris@101
|
93 }
|
Chris@16
|
94
|
Chris@16
|
95 private:
|
Chris@16
|
96 void increment()
|
Chris@16
|
97 {
|
Chris@101
|
98 for (difference_type i = 0;
|
Chris@101
|
99 (m_it != m_last) && (i < m_stride); ++i)
|
Chris@101
|
100 {
|
Chris@101
|
101 ++m_it;
|
Chris@101
|
102 }
|
Chris@16
|
103 }
|
Chris@16
|
104
|
Chris@101
|
105 reference dereference() const
|
Chris@101
|
106 {
|
Chris@101
|
107 return *m_it;
|
Chris@101
|
108 }
|
Chris@101
|
109
|
Chris@101
|
110 template<class OtherIterator>
|
Chris@101
|
111 bool equal(
|
Chris@101
|
112 const strided_iterator<OtherIterator, Category>& other,
|
Chris@101
|
113 typename enable_if_convertible<
|
Chris@101
|
114 OtherIterator,
|
Chris@101
|
115 base_iterator
|
Chris@101
|
116 >::type* = 0) const
|
Chris@101
|
117 {
|
Chris@101
|
118 return m_it == other.m_it;
|
Chris@101
|
119 }
|
Chris@101
|
120
|
Chris@101
|
121 base_iterator m_it;
|
Chris@16
|
122 base_iterator m_last;
|
Chris@16
|
123 difference_type m_stride;
|
Chris@16
|
124 };
|
Chris@16
|
125
|
Chris@16
|
126 // strided_iterator for wrapping a bidirectional iterator
|
Chris@16
|
127 template<class BaseIterator>
|
Chris@16
|
128 class strided_iterator<BaseIterator, bidirectional_traversal_tag>
|
Chris@101
|
129 : public iterator_facade<
|
Chris@16
|
130 strided_iterator<BaseIterator, bidirectional_traversal_tag>
|
Chris@101
|
131 , typename iterator_value<BaseIterator>::type
|
Chris@101
|
132 , bidirectional_traversal_tag
|
Chris@101
|
133 , typename iterator_reference<BaseIterator>::type
|
Chris@101
|
134 , typename iterator_difference<BaseIterator>::type
|
Chris@16
|
135 >
|
Chris@16
|
136 {
|
Chris@16
|
137 friend class ::boost::iterator_core_access;
|
Chris@16
|
138
|
Chris@101
|
139 typedef iterator_facade<
|
Chris@101
|
140 strided_iterator<BaseIterator, bidirectional_traversal_tag>
|
Chris@101
|
141 , typename iterator_value<BaseIterator>::type
|
Chris@101
|
142 , bidirectional_traversal_tag
|
Chris@101
|
143 , typename iterator_reference<BaseIterator>::type
|
Chris@101
|
144 , typename iterator_difference<BaseIterator>::type
|
Chris@101
|
145 > super_t;
|
Chris@16
|
146 public:
|
Chris@101
|
147 typedef typename super_t::difference_type difference_type;
|
Chris@101
|
148 typedef typename super_t::reference reference;
|
Chris@16
|
149 typedef BaseIterator base_iterator;
|
Chris@101
|
150 typedef typename boost::make_unsigned<difference_type>::type
|
Chris@101
|
151 size_type;
|
Chris@101
|
152 typedef std::bidirectional_iterator_tag iterator_category;
|
Chris@16
|
153
|
Chris@16
|
154 strided_iterator()
|
Chris@101
|
155 : m_it()
|
Chris@101
|
156 , m_offset()
|
Chris@101
|
157 , m_index()
|
Chris@16
|
158 , m_stride()
|
Chris@16
|
159 {
|
Chris@16
|
160 }
|
Chris@16
|
161
|
Chris@101
|
162 strided_iterator(base_iterator it,
|
Chris@101
|
163 size_type index,
|
Chris@101
|
164 difference_type stride)
|
Chris@101
|
165 : m_it(it)
|
Chris@101
|
166 , m_offset()
|
Chris@101
|
167 , m_index(index)
|
Chris@16
|
168 , m_stride(stride)
|
Chris@16
|
169 {
|
Chris@101
|
170 if (stride && ((m_index % stride) != 0))
|
Chris@101
|
171 m_index += (stride - (m_index % stride));
|
Chris@16
|
172 }
|
Chris@16
|
173
|
Chris@16
|
174 template<class OtherIterator>
|
Chris@101
|
175 strided_iterator(
|
Chris@101
|
176 const strided_iterator<
|
Chris@101
|
177 OtherIterator,
|
Chris@101
|
178 bidirectional_traversal_tag
|
Chris@101
|
179 >& other,
|
Chris@101
|
180 typename enable_if_convertible<
|
Chris@101
|
181 OtherIterator,
|
Chris@101
|
182 base_iterator
|
Chris@101
|
183 >::type* = 0
|
Chris@101
|
184 )
|
Chris@101
|
185 : m_it(other.base())
|
Chris@101
|
186 , m_offset(other.get_offset())
|
Chris@101
|
187 , m_index(other.get_index())
|
Chris@16
|
188 , m_stride(other.get_stride())
|
Chris@16
|
189 {
|
Chris@16
|
190 }
|
Chris@16
|
191
|
Chris@101
|
192 base_iterator base() const
|
Chris@101
|
193 {
|
Chris@101
|
194 return m_it;
|
Chris@101
|
195 }
|
Chris@101
|
196
|
Chris@101
|
197 difference_type get_offset() const
|
Chris@101
|
198 {
|
Chris@101
|
199 return m_offset;
|
Chris@101
|
200 }
|
Chris@101
|
201
|
Chris@101
|
202 size_type get_index() const
|
Chris@101
|
203 {
|
Chris@101
|
204 return m_index;
|
Chris@101
|
205 }
|
Chris@101
|
206
|
Chris@101
|
207 difference_type get_stride() const
|
Chris@101
|
208 {
|
Chris@101
|
209 return m_stride;
|
Chris@101
|
210 }
|
Chris@16
|
211
|
Chris@16
|
212 private:
|
Chris@16
|
213 void increment()
|
Chris@16
|
214 {
|
Chris@101
|
215 m_offset += m_stride;
|
Chris@16
|
216 }
|
Chris@16
|
217
|
Chris@16
|
218 void decrement()
|
Chris@16
|
219 {
|
Chris@101
|
220 m_offset -= m_stride;
|
Chris@16
|
221 }
|
Chris@16
|
222
|
Chris@101
|
223 reference dereference() const
|
Chris@101
|
224 {
|
Chris@101
|
225 update();
|
Chris@101
|
226 return *m_it;
|
Chris@101
|
227 }
|
Chris@101
|
228
|
Chris@101
|
229 void update() const
|
Chris@101
|
230 {
|
Chris@101
|
231 std::advance(m_it, m_offset);
|
Chris@101
|
232 m_index += m_offset;
|
Chris@101
|
233 m_offset = 0;
|
Chris@101
|
234 }
|
Chris@101
|
235
|
Chris@101
|
236 template<class OtherIterator>
|
Chris@101
|
237 bool equal(
|
Chris@101
|
238 const strided_iterator<
|
Chris@101
|
239 OtherIterator,
|
Chris@101
|
240 bidirectional_traversal_tag
|
Chris@101
|
241 >& other,
|
Chris@101
|
242 typename enable_if_convertible<
|
Chris@101
|
243 OtherIterator,
|
Chris@101
|
244 base_iterator
|
Chris@101
|
245 >::type* = 0) const
|
Chris@101
|
246 {
|
Chris@101
|
247 return (m_index + m_offset) ==
|
Chris@101
|
248 (other.get_index() + other.get_offset());
|
Chris@101
|
249 }
|
Chris@101
|
250
|
Chris@101
|
251 mutable base_iterator m_it;
|
Chris@101
|
252 mutable difference_type m_offset;
|
Chris@101
|
253 mutable size_type m_index;
|
Chris@16
|
254 difference_type m_stride;
|
Chris@16
|
255 };
|
Chris@16
|
256
|
Chris@16
|
257 // strided_iterator implementation for wrapping a random access iterator
|
Chris@16
|
258 template<class BaseIterator>
|
Chris@16
|
259 class strided_iterator<BaseIterator, random_access_traversal_tag>
|
Chris@101
|
260 : public iterator_facade<
|
Chris@101
|
261 strided_iterator<BaseIterator, random_access_traversal_tag>
|
Chris@101
|
262 , typename iterator_value<BaseIterator>::type
|
Chris@101
|
263 , random_access_traversal_tag
|
Chris@101
|
264 , typename iterator_reference<BaseIterator>::type
|
Chris@101
|
265 , typename iterator_difference<BaseIterator>::type
|
Chris@101
|
266 >
|
Chris@16
|
267 {
|
Chris@16
|
268 friend class ::boost::iterator_core_access;
|
Chris@16
|
269
|
Chris@101
|
270 typedef iterator_facade<
|
Chris@101
|
271 strided_iterator<BaseIterator, random_access_traversal_tag>
|
Chris@101
|
272 , typename iterator_value<BaseIterator>::type
|
Chris@101
|
273 , random_access_traversal_tag
|
Chris@101
|
274 , typename iterator_reference<BaseIterator>::type
|
Chris@101
|
275 , typename iterator_difference<BaseIterator>::type
|
Chris@101
|
276 > super_t;
|
Chris@16
|
277 public:
|
Chris@101
|
278 typedef typename super_t::difference_type difference_type;
|
Chris@101
|
279 typedef typename super_t::reference reference;
|
Chris@16
|
280 typedef BaseIterator base_iterator;
|
Chris@101
|
281 typedef std::random_access_iterator_tag iterator_category;
|
Chris@16
|
282
|
Chris@16
|
283 strided_iterator()
|
Chris@101
|
284 : m_it()
|
Chris@101
|
285 , m_first()
|
Chris@16
|
286 , m_index(0)
|
Chris@16
|
287 , m_stride()
|
Chris@16
|
288 {
|
Chris@16
|
289 }
|
Chris@16
|
290
|
Chris@101
|
291 strided_iterator(
|
Chris@101
|
292 base_iterator first,
|
Chris@101
|
293 base_iterator it,
|
Chris@101
|
294 difference_type stride
|
Chris@101
|
295 )
|
Chris@101
|
296 : m_it(it)
|
Chris@16
|
297 , m_first(first)
|
Chris@101
|
298 , m_index(stride ? (it - first) : difference_type())
|
Chris@16
|
299 , m_stride(stride)
|
Chris@16
|
300 {
|
Chris@101
|
301 if (stride && ((m_index % stride) != 0))
|
Chris@101
|
302 m_index += (stride - (m_index % stride));
|
Chris@16
|
303 }
|
Chris@16
|
304
|
Chris@16
|
305 template<class OtherIterator>
|
Chris@101
|
306 strided_iterator(
|
Chris@101
|
307 const strided_iterator<
|
Chris@101
|
308 OtherIterator,
|
Chris@101
|
309 random_access_traversal_tag
|
Chris@101
|
310 >& other,
|
Chris@101
|
311 typename enable_if_convertible<
|
Chris@101
|
312 OtherIterator,
|
Chris@101
|
313 base_iterator
|
Chris@101
|
314 >::type* = 0
|
Chris@101
|
315 )
|
Chris@101
|
316 : m_it(other.base())
|
Chris@16
|
317 , m_first(other.base_begin())
|
Chris@16
|
318 , m_index(other.get_index())
|
Chris@16
|
319 , m_stride(other.get_stride())
|
Chris@16
|
320 {
|
Chris@16
|
321 }
|
Chris@16
|
322
|
Chris@101
|
323 base_iterator base_begin() const
|
Chris@101
|
324 {
|
Chris@101
|
325 return m_first;
|
Chris@101
|
326 }
|
Chris@101
|
327
|
Chris@101
|
328 base_iterator base() const
|
Chris@101
|
329 {
|
Chris@101
|
330 return m_it;
|
Chris@101
|
331 }
|
Chris@101
|
332
|
Chris@101
|
333 difference_type get_stride() const
|
Chris@101
|
334 {
|
Chris@101
|
335 return m_stride;
|
Chris@101
|
336 }
|
Chris@101
|
337
|
Chris@101
|
338 difference_type get_index() const
|
Chris@101
|
339 {
|
Chris@101
|
340 return m_index;
|
Chris@101
|
341 }
|
Chris@16
|
342
|
Chris@16
|
343 private:
|
Chris@16
|
344 void increment()
|
Chris@16
|
345 {
|
Chris@16
|
346 m_index += m_stride;
|
Chris@16
|
347 }
|
Chris@16
|
348
|
Chris@16
|
349 void decrement()
|
Chris@16
|
350 {
|
Chris@16
|
351 m_index -= m_stride;
|
Chris@16
|
352 }
|
Chris@16
|
353
|
Chris@16
|
354 void advance(difference_type offset)
|
Chris@16
|
355 {
|
Chris@101
|
356 m_index += (m_stride * offset);
|
Chris@101
|
357 }
|
Chris@101
|
358
|
Chris@101
|
359 // Implementation detail: only update the actual underlying iterator
|
Chris@101
|
360 // at the point of dereference. This is done so that the increment
|
Chris@101
|
361 // and decrement can overshoot the valid sequence as is required
|
Chris@101
|
362 // by striding. Since we can do all comparisons just with the index
|
Chris@101
|
363 // simply, and all dereferences must be within the valid range.
|
Chris@101
|
364 void update() const
|
Chris@101
|
365 {
|
Chris@101
|
366 m_it = m_first + m_index;
|
Chris@16
|
367 }
|
Chris@16
|
368
|
Chris@16
|
369 template<class OtherIterator>
|
Chris@101
|
370 difference_type distance_to(
|
Chris@101
|
371 const strided_iterator<
|
Chris@101
|
372 OtherIterator,
|
Chris@101
|
373 random_access_traversal_tag
|
Chris@101
|
374 >& other,
|
Chris@101
|
375 typename enable_if_convertible<
|
Chris@101
|
376 OtherIterator, base_iterator>::type* = 0) const
|
Chris@16
|
377 {
|
Chris@101
|
378 BOOST_ASSERT((other.m_index - m_index) % m_stride == difference_type());
|
Chris@101
|
379 return (other.m_index - m_index) / m_stride;
|
Chris@16
|
380 }
|
Chris@16
|
381
|
Chris@101
|
382 template<class OtherIterator>
|
Chris@101
|
383 bool equal(
|
Chris@101
|
384 const strided_iterator<
|
Chris@101
|
385 OtherIterator,
|
Chris@101
|
386 random_access_traversal_tag
|
Chris@101
|
387 >& other,
|
Chris@101
|
388 typename enable_if_convertible<
|
Chris@101
|
389 OtherIterator, base_iterator>::type* = 0) const
|
Chris@16
|
390 {
|
Chris@101
|
391 return m_index == other.m_index;
|
Chris@101
|
392 }
|
Chris@101
|
393
|
Chris@101
|
394 reference dereference() const
|
Chris@101
|
395 {
|
Chris@101
|
396 update();
|
Chris@101
|
397 return *m_it;
|
Chris@16
|
398 }
|
Chris@16
|
399
|
Chris@16
|
400 private:
|
Chris@101
|
401 mutable base_iterator m_it;
|
Chris@16
|
402 base_iterator m_first;
|
Chris@16
|
403 difference_type m_index;
|
Chris@16
|
404 difference_type m_stride;
|
Chris@16
|
405 };
|
Chris@16
|
406
|
Chris@101
|
407 template<class Rng, class Difference> inline
|
Chris@101
|
408 strided_iterator<
|
Chris@101
|
409 typename range_iterator<Rng>::type,
|
Chris@101
|
410 forward_traversal_tag
|
Chris@101
|
411 >
|
Chris@101
|
412 make_begin_strided_iterator(
|
Chris@101
|
413 Rng& rng,
|
Chris@101
|
414 Difference stride,
|
Chris@101
|
415 forward_traversal_tag)
|
Chris@16
|
416 {
|
Chris@101
|
417 return strided_iterator<
|
Chris@101
|
418 typename range_iterator<Rng>::type,
|
Chris@101
|
419 forward_traversal_tag
|
Chris@101
|
420 >(boost::begin(rng), boost::end(rng), stride);
|
Chris@16
|
421 }
|
Chris@16
|
422
|
Chris@101
|
423 template<class Rng, class Difference> inline
|
Chris@101
|
424 strided_iterator<
|
Chris@101
|
425 typename range_iterator<const Rng>::type,
|
Chris@101
|
426 forward_traversal_tag
|
Chris@101
|
427 >
|
Chris@101
|
428 make_begin_strided_iterator(
|
Chris@101
|
429 const Rng& rng,
|
Chris@101
|
430 Difference stride,
|
Chris@101
|
431 forward_traversal_tag)
|
Chris@101
|
432 {
|
Chris@101
|
433 return strided_iterator<
|
Chris@101
|
434 typename range_iterator<const Rng>::type,
|
Chris@101
|
435 forward_traversal_tag
|
Chris@101
|
436 >(boost::begin(rng), boost::end(rng), stride);
|
Chris@101
|
437 }
|
Chris@101
|
438
|
Chris@101
|
439 template<class Rng, class Difference> inline
|
Chris@101
|
440 strided_iterator<
|
Chris@101
|
441 typename range_iterator<Rng>::type,
|
Chris@101
|
442 forward_traversal_tag
|
Chris@101
|
443 >
|
Chris@101
|
444 make_end_strided_iterator(
|
Chris@101
|
445 Rng& rng,
|
Chris@101
|
446 Difference stride,
|
Chris@101
|
447 forward_traversal_tag)
|
Chris@101
|
448 {
|
Chris@101
|
449 return strided_iterator<
|
Chris@101
|
450 typename range_iterator<Rng>::type,
|
Chris@101
|
451 forward_traversal_tag
|
Chris@101
|
452 >(boost::end(rng), boost::end(rng), stride);
|
Chris@101
|
453 }
|
Chris@101
|
454
|
Chris@101
|
455 template<class Rng, class Difference> inline
|
Chris@101
|
456 strided_iterator<
|
Chris@101
|
457 typename range_iterator<const Rng>::type,
|
Chris@101
|
458 forward_traversal_tag
|
Chris@101
|
459 >
|
Chris@101
|
460 make_end_strided_iterator(
|
Chris@101
|
461 const Rng& rng,
|
Chris@101
|
462 Difference stride,
|
Chris@101
|
463 forward_traversal_tag)
|
Chris@101
|
464 {
|
Chris@101
|
465 return strided_iterator<
|
Chris@101
|
466 typename range_iterator<const Rng>::type,
|
Chris@101
|
467 forward_traversal_tag
|
Chris@101
|
468 >(boost::end(rng), boost::end(rng), stride);
|
Chris@101
|
469 }
|
Chris@101
|
470
|
Chris@101
|
471 template<class Rng, class Difference> inline
|
Chris@101
|
472 strided_iterator<
|
Chris@101
|
473 typename range_iterator<Rng>::type,
|
Chris@101
|
474 bidirectional_traversal_tag
|
Chris@101
|
475 >
|
Chris@101
|
476 make_begin_strided_iterator(
|
Chris@101
|
477 Rng& rng,
|
Chris@101
|
478 Difference stride,
|
Chris@101
|
479 bidirectional_traversal_tag)
|
Chris@101
|
480 {
|
Chris@101
|
481 typedef typename range_difference<Rng>::type difference_type;
|
Chris@101
|
482
|
Chris@101
|
483 return strided_iterator<
|
Chris@101
|
484 typename range_iterator<Rng>::type,
|
Chris@101
|
485 bidirectional_traversal_tag
|
Chris@101
|
486 >(boost::begin(rng), difference_type(), stride);
|
Chris@101
|
487 }
|
Chris@101
|
488
|
Chris@101
|
489 template<class Rng, class Difference> inline
|
Chris@101
|
490 strided_iterator<
|
Chris@101
|
491 typename range_iterator<const Rng>::type,
|
Chris@101
|
492 bidirectional_traversal_tag
|
Chris@101
|
493 >
|
Chris@101
|
494 make_begin_strided_iterator(
|
Chris@101
|
495 const Rng& rng,
|
Chris@101
|
496 Difference stride,
|
Chris@101
|
497 bidirectional_traversal_tag)
|
Chris@101
|
498 {
|
Chris@101
|
499 typedef typename range_difference<const Rng>::type difference_type;
|
Chris@101
|
500
|
Chris@101
|
501 return strided_iterator<
|
Chris@101
|
502 typename range_iterator<const Rng>::type,
|
Chris@101
|
503 bidirectional_traversal_tag
|
Chris@101
|
504 >(boost::begin(rng), difference_type(), stride);
|
Chris@101
|
505 }
|
Chris@101
|
506
|
Chris@101
|
507 template<class Rng, class Difference> inline
|
Chris@101
|
508 strided_iterator<
|
Chris@101
|
509 typename range_iterator<Rng>::type,
|
Chris@101
|
510 bidirectional_traversal_tag
|
Chris@101
|
511 >
|
Chris@101
|
512 make_end_strided_iterator(
|
Chris@101
|
513 Rng& rng,
|
Chris@101
|
514 Difference stride,
|
Chris@101
|
515 bidirectional_traversal_tag)
|
Chris@101
|
516 {
|
Chris@101
|
517 return strided_iterator<
|
Chris@101
|
518 typename range_iterator<Rng>::type,
|
Chris@101
|
519 bidirectional_traversal_tag
|
Chris@101
|
520 >(boost::end(rng), boost::size(rng), stride);
|
Chris@101
|
521 }
|
Chris@101
|
522
|
Chris@101
|
523 template<class Rng, class Difference> inline
|
Chris@101
|
524 strided_iterator<
|
Chris@101
|
525 typename range_iterator<const Rng>::type,
|
Chris@101
|
526 bidirectional_traversal_tag
|
Chris@101
|
527 >
|
Chris@101
|
528 make_end_strided_iterator(
|
Chris@101
|
529 const Rng& rng,
|
Chris@101
|
530 Difference stride,
|
Chris@101
|
531 bidirectional_traversal_tag)
|
Chris@101
|
532 {
|
Chris@101
|
533 return strided_iterator<
|
Chris@101
|
534 typename range_iterator<const Rng>::type,
|
Chris@101
|
535 bidirectional_traversal_tag
|
Chris@101
|
536 >(boost::end(rng), boost::size(rng), stride);
|
Chris@101
|
537 }
|
Chris@101
|
538
|
Chris@101
|
539 template<class Rng, class Difference> inline
|
Chris@101
|
540 strided_iterator<
|
Chris@101
|
541 typename range_iterator<Rng>::type,
|
Chris@101
|
542 random_access_traversal_tag
|
Chris@101
|
543 >
|
Chris@101
|
544 make_begin_strided_iterator(
|
Chris@101
|
545 Rng& rng,
|
Chris@101
|
546 Difference stride,
|
Chris@101
|
547 random_access_traversal_tag)
|
Chris@101
|
548 {
|
Chris@101
|
549 return strided_iterator<
|
Chris@101
|
550 typename range_iterator<Rng>::type,
|
Chris@101
|
551 random_access_traversal_tag
|
Chris@101
|
552 >(boost::begin(rng), boost::begin(rng), stride);
|
Chris@101
|
553 }
|
Chris@101
|
554
|
Chris@101
|
555 template<class Rng, class Difference> inline
|
Chris@101
|
556 strided_iterator<
|
Chris@101
|
557 typename range_iterator<const Rng>::type,
|
Chris@101
|
558 random_access_traversal_tag
|
Chris@101
|
559 >
|
Chris@101
|
560 make_begin_strided_iterator(
|
Chris@101
|
561 const Rng& rng,
|
Chris@101
|
562 Difference stride,
|
Chris@101
|
563 random_access_traversal_tag)
|
Chris@101
|
564 {
|
Chris@101
|
565 return strided_iterator<
|
Chris@101
|
566 typename range_iterator<const Rng>::type,
|
Chris@101
|
567 random_access_traversal_tag
|
Chris@101
|
568 >(boost::begin(rng), boost::begin(rng), stride);
|
Chris@101
|
569 }
|
Chris@101
|
570
|
Chris@101
|
571 template<class Rng, class Difference> inline
|
Chris@101
|
572 strided_iterator<
|
Chris@101
|
573 typename range_iterator<Rng>::type,
|
Chris@101
|
574 random_access_traversal_tag
|
Chris@101
|
575 >
|
Chris@101
|
576 make_end_strided_iterator(
|
Chris@101
|
577 Rng& rng,
|
Chris@101
|
578 Difference stride,
|
Chris@101
|
579 random_access_traversal_tag)
|
Chris@101
|
580 {
|
Chris@101
|
581 return strided_iterator<
|
Chris@101
|
582 typename range_iterator<Rng>::type,
|
Chris@101
|
583 random_access_traversal_tag
|
Chris@101
|
584 >(boost::begin(rng), boost::end(rng), stride);
|
Chris@101
|
585 }
|
Chris@101
|
586
|
Chris@101
|
587 template<class Rng, class Difference> inline
|
Chris@101
|
588 strided_iterator<
|
Chris@101
|
589 typename range_iterator<const Rng>::type,
|
Chris@101
|
590 random_access_traversal_tag
|
Chris@101
|
591 >
|
Chris@101
|
592 make_end_strided_iterator(
|
Chris@101
|
593 const Rng& rng,
|
Chris@101
|
594 Difference stride,
|
Chris@101
|
595 random_access_traversal_tag)
|
Chris@101
|
596 {
|
Chris@101
|
597 return strided_iterator<
|
Chris@101
|
598 typename range_iterator<const Rng>::type,
|
Chris@101
|
599 random_access_traversal_tag
|
Chris@101
|
600 >(boost::begin(rng), boost::end(rng), stride);
|
Chris@101
|
601 }
|
Chris@101
|
602
|
Chris@101
|
603 template<
|
Chris@101
|
604 class Rng,
|
Chris@101
|
605 class Category =
|
Chris@101
|
606 typename iterator_traversal<
|
Chris@101
|
607 typename range_iterator<Rng>::type
|
Chris@101
|
608 >::type
|
Chris@101
|
609 >
|
Chris@16
|
610 class strided_range
|
Chris@16
|
611 : public iterator_range<
|
Chris@101
|
612 range_detail::strided_iterator<
|
Chris@101
|
613 typename range_iterator<Rng>::type,
|
Chris@101
|
614 Category
|
Chris@101
|
615 >
|
Chris@101
|
616 >
|
Chris@16
|
617 {
|
Chris@16
|
618 typedef range_detail::strided_iterator<
|
Chris@101
|
619 typename range_iterator<Rng>::type,
|
Chris@101
|
620 Category
|
Chris@101
|
621 > iter_type;
|
Chris@16
|
622 typedef iterator_range<iter_type> super_t;
|
Chris@16
|
623 public:
|
Chris@16
|
624 template<class Difference>
|
Chris@16
|
625 strided_range(Difference stride, Rng& rng)
|
Chris@101
|
626 : super_t(
|
Chris@101
|
627 range_detail::make_begin_strided_iterator(
|
Chris@101
|
628 rng, stride,
|
Chris@101
|
629 typename iterator_traversal<
|
Chris@101
|
630 typename range_iterator<Rng>::type
|
Chris@101
|
631 >::type()),
|
Chris@101
|
632 range_detail::make_end_strided_iterator(
|
Chris@101
|
633 rng, stride,
|
Chris@101
|
634 typename iterator_traversal<
|
Chris@101
|
635 typename range_iterator<Rng>::type
|
Chris@101
|
636 >::type()))
|
Chris@16
|
637 {
|
Chris@16
|
638 BOOST_ASSERT( stride >= 0 );
|
Chris@16
|
639 }
|
Chris@16
|
640 };
|
Chris@16
|
641
|
Chris@16
|
642 template<class Difference>
|
Chris@16
|
643 class strided_holder : public holder<Difference>
|
Chris@16
|
644 {
|
Chris@16
|
645 public:
|
Chris@101
|
646 explicit strided_holder(Difference value)
|
Chris@101
|
647 : holder<Difference>(value)
|
Chris@101
|
648 {
|
Chris@101
|
649 }
|
Chris@16
|
650 };
|
Chris@16
|
651
|
Chris@16
|
652 template<class Rng, class Difference>
|
Chris@16
|
653 inline strided_range<Rng>
|
Chris@16
|
654 operator|(Rng& rng, const strided_holder<Difference>& stride)
|
Chris@16
|
655 {
|
Chris@16
|
656 return strided_range<Rng>(stride.val, rng);
|
Chris@16
|
657 }
|
Chris@16
|
658
|
Chris@16
|
659 template<class Rng, class Difference>
|
Chris@16
|
660 inline strided_range<const Rng>
|
Chris@16
|
661 operator|(const Rng& rng, const strided_holder<Difference>& stride)
|
Chris@16
|
662 {
|
Chris@16
|
663 return strided_range<const Rng>(stride.val, rng);
|
Chris@16
|
664 }
|
Chris@16
|
665
|
Chris@16
|
666 } // namespace range_detail
|
Chris@16
|
667
|
Chris@16
|
668 using range_detail::strided_range;
|
Chris@16
|
669
|
Chris@16
|
670 namespace adaptors
|
Chris@16
|
671 {
|
Chris@16
|
672
|
Chris@16
|
673 namespace
|
Chris@16
|
674 {
|
Chris@16
|
675 const range_detail::forwarder<range_detail::strided_holder>
|
Chris@101
|
676 strided = range_detail::forwarder<
|
Chris@101
|
677 range_detail::strided_holder>();
|
Chris@16
|
678 }
|
Chris@16
|
679
|
Chris@16
|
680 template<class Range, class Difference>
|
Chris@16
|
681 inline strided_range<Range>
|
Chris@16
|
682 stride(Range& rng, Difference step)
|
Chris@16
|
683 {
|
Chris@16
|
684 return strided_range<Range>(step, rng);
|
Chris@16
|
685 }
|
Chris@16
|
686
|
Chris@16
|
687 template<class Range, class Difference>
|
Chris@16
|
688 inline strided_range<const Range>
|
Chris@16
|
689 stride(const Range& rng, Difference step)
|
Chris@16
|
690 {
|
Chris@16
|
691 return strided_range<const Range>(step, rng);
|
Chris@16
|
692 }
|
Chris@16
|
693
|
Chris@16
|
694 } // namespace 'adaptors'
|
Chris@16
|
695 } // namespace 'boost'
|
Chris@16
|
696
|
Chris@16
|
697 #endif
|