File indexing completed on 2025-01-18 09:51:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED
0012 #define BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED
0013
0014 #include <boost/range/adaptor/argument_fwd.hpp>
0015 #include <boost/range/iterator_range.hpp>
0016 #include <boost/iterator/iterator_facade.hpp>
0017 #include <iterator>
0018
0019 namespace boost
0020 {
0021 namespace range_detail
0022 {
0023
0024 template<class BaseIterator, class Category>
0025 class strided_iterator
0026 : public iterator_facade<
0027 strided_iterator<BaseIterator, Category>
0028 , typename iterator_value<BaseIterator>::type
0029 , forward_traversal_tag
0030 , typename iterator_reference<BaseIterator>::type
0031 , typename iterator_difference<BaseIterator>::type
0032 >
0033 {
0034 friend class ::boost::iterator_core_access;
0035
0036 typedef iterator_facade<
0037 strided_iterator<BaseIterator, Category>
0038 , typename iterator_value<BaseIterator>::type
0039 , forward_traversal_tag
0040 , typename iterator_reference<BaseIterator>::type
0041 , typename iterator_difference<BaseIterator>::type
0042 > super_t;
0043
0044 public:
0045 typedef typename super_t::difference_type difference_type;
0046 typedef typename super_t::reference reference;
0047 typedef BaseIterator base_iterator;
0048 typedef std::forward_iterator_tag iterator_category;
0049
0050 strided_iterator()
0051 : m_it()
0052 , m_last()
0053 , m_stride()
0054 {
0055 }
0056
0057 strided_iterator(base_iterator it,
0058 base_iterator last,
0059 difference_type stride)
0060 : m_it(it)
0061 , m_last(last)
0062 , m_stride(stride)
0063 {
0064 }
0065
0066 template<class OtherIterator>
0067 strided_iterator(
0068 const strided_iterator<OtherIterator, Category>& other,
0069 typename enable_if_convertible<
0070 OtherIterator,
0071 base_iterator
0072 >::type* = 0
0073 )
0074 : m_it(other.base())
0075 , m_last(other.base_end())
0076 , m_stride(other.get_stride())
0077 {
0078 }
0079
0080 base_iterator base() const
0081 {
0082 return m_it;
0083 }
0084
0085 base_iterator base_end() const
0086 {
0087 return m_last;
0088 }
0089
0090 difference_type get_stride() const
0091 {
0092 return m_stride;
0093 }
0094
0095 private:
0096 void increment()
0097 {
0098 for (difference_type i = 0;
0099 (m_it != m_last) && (i < m_stride); ++i)
0100 {
0101 ++m_it;
0102 }
0103 }
0104
0105 reference dereference() const
0106 {
0107 return *m_it;
0108 }
0109
0110 template<class OtherIterator>
0111 bool equal(
0112 const strided_iterator<OtherIterator, Category>& other,
0113 typename enable_if_convertible<
0114 OtherIterator,
0115 base_iterator
0116 >::type* = 0) const
0117 {
0118 return m_it == other.m_it;
0119 }
0120
0121 base_iterator m_it;
0122 base_iterator m_last;
0123 difference_type m_stride;
0124 };
0125
0126
0127 template<class BaseIterator>
0128 class strided_iterator<BaseIterator, bidirectional_traversal_tag>
0129 : public iterator_facade<
0130 strided_iterator<BaseIterator, bidirectional_traversal_tag>
0131 , typename iterator_value<BaseIterator>::type
0132 , bidirectional_traversal_tag
0133 , typename iterator_reference<BaseIterator>::type
0134 , typename iterator_difference<BaseIterator>::type
0135 >
0136 {
0137 friend class ::boost::iterator_core_access;
0138
0139 typedef iterator_facade<
0140 strided_iterator<BaseIterator, bidirectional_traversal_tag>
0141 , typename iterator_value<BaseIterator>::type
0142 , bidirectional_traversal_tag
0143 , typename iterator_reference<BaseIterator>::type
0144 , typename iterator_difference<BaseIterator>::type
0145 > super_t;
0146 public:
0147 typedef typename super_t::difference_type difference_type;
0148 typedef typename super_t::reference reference;
0149 typedef BaseIterator base_iterator;
0150 typedef typename boost::make_unsigned<difference_type>::type
0151 size_type;
0152 typedef std::bidirectional_iterator_tag iterator_category;
0153
0154 strided_iterator()
0155 : m_it()
0156 , m_offset()
0157 , m_index()
0158 , m_stride()
0159 {
0160 }
0161
0162 strided_iterator(base_iterator it,
0163 size_type index,
0164 difference_type stride)
0165 : m_it(it)
0166 , m_offset()
0167 , m_index(index)
0168 , m_stride(stride)
0169 {
0170 if (stride && ((m_index % stride) != 0))
0171 m_index += (stride - (m_index % stride));
0172 }
0173
0174 template<class OtherIterator>
0175 strided_iterator(
0176 const strided_iterator<
0177 OtherIterator,
0178 bidirectional_traversal_tag
0179 >& other,
0180 typename enable_if_convertible<
0181 OtherIterator,
0182 base_iterator
0183 >::type* = 0
0184 )
0185 : m_it(other.base())
0186 , m_offset(other.get_offset())
0187 , m_index(other.get_index())
0188 , m_stride(other.get_stride())
0189 {
0190 }
0191
0192 base_iterator base() const
0193 {
0194 return m_it;
0195 }
0196
0197 difference_type get_offset() const
0198 {
0199 return m_offset;
0200 }
0201
0202 size_type get_index() const
0203 {
0204 return m_index;
0205 }
0206
0207 difference_type get_stride() const
0208 {
0209 return m_stride;
0210 }
0211
0212 private:
0213 void increment()
0214 {
0215 m_offset += m_stride;
0216 }
0217
0218 void decrement()
0219 {
0220 m_offset -= m_stride;
0221 }
0222
0223 reference dereference() const
0224 {
0225 update();
0226 return *m_it;
0227 }
0228
0229 void update() const
0230 {
0231 std::advance(m_it, m_offset);
0232 m_index += m_offset;
0233 m_offset = 0;
0234 }
0235
0236 template<class OtherIterator>
0237 bool equal(
0238 const strided_iterator<
0239 OtherIterator,
0240 bidirectional_traversal_tag
0241 >& other,
0242 typename enable_if_convertible<
0243 OtherIterator,
0244 base_iterator
0245 >::type* = 0) const
0246 {
0247 return (m_index + m_offset) ==
0248 (other.get_index() + other.get_offset());
0249 }
0250
0251 mutable base_iterator m_it;
0252 mutable difference_type m_offset;
0253 mutable size_type m_index;
0254 difference_type m_stride;
0255 };
0256
0257
0258 template<class BaseIterator>
0259 class strided_iterator<BaseIterator, random_access_traversal_tag>
0260 : public iterator_facade<
0261 strided_iterator<BaseIterator, random_access_traversal_tag>
0262 , typename iterator_value<BaseIterator>::type
0263 , random_access_traversal_tag
0264 , typename iterator_reference<BaseIterator>::type
0265 , typename iterator_difference<BaseIterator>::type
0266 >
0267 {
0268 friend class ::boost::iterator_core_access;
0269
0270 typedef iterator_facade<
0271 strided_iterator<BaseIterator, random_access_traversal_tag>
0272 , typename iterator_value<BaseIterator>::type
0273 , random_access_traversal_tag
0274 , typename iterator_reference<BaseIterator>::type
0275 , typename iterator_difference<BaseIterator>::type
0276 > super_t;
0277 public:
0278 typedef typename super_t::difference_type difference_type;
0279 typedef typename super_t::reference reference;
0280 typedef BaseIterator base_iterator;
0281 typedef std::random_access_iterator_tag iterator_category;
0282
0283 strided_iterator()
0284 : m_it()
0285 , m_first()
0286 , m_index(0)
0287 , m_stride()
0288 {
0289 }
0290
0291 strided_iterator(
0292 base_iterator first,
0293 base_iterator it,
0294 difference_type stride
0295 )
0296 : m_it(it)
0297 , m_first(first)
0298 , m_index(stride ? (it - first) : difference_type())
0299 , m_stride(stride)
0300 {
0301 if (stride && ((m_index % stride) != 0))
0302 m_index += (stride - (m_index % stride));
0303 }
0304
0305 template<class OtherIterator>
0306 strided_iterator(
0307 const strided_iterator<
0308 OtherIterator,
0309 random_access_traversal_tag
0310 >& other,
0311 typename enable_if_convertible<
0312 OtherIterator,
0313 base_iterator
0314 >::type* = 0
0315 )
0316 : m_it(other.base())
0317 , m_first(other.base_begin())
0318 , m_index(other.get_index())
0319 , m_stride(other.get_stride())
0320 {
0321 }
0322
0323 base_iterator base_begin() const
0324 {
0325 return m_first;
0326 }
0327
0328 base_iterator base() const
0329 {
0330 return m_it;
0331 }
0332
0333 difference_type get_stride() const
0334 {
0335 return m_stride;
0336 }
0337
0338 difference_type get_index() const
0339 {
0340 return m_index;
0341 }
0342
0343 private:
0344 void increment()
0345 {
0346 m_index += m_stride;
0347 }
0348
0349 void decrement()
0350 {
0351 m_index -= m_stride;
0352 }
0353
0354 void advance(difference_type offset)
0355 {
0356 m_index += (m_stride * offset);
0357 }
0358
0359
0360
0361
0362
0363
0364 void update() const
0365 {
0366 m_it = m_first + m_index;
0367 }
0368
0369 template<class OtherIterator>
0370 difference_type distance_to(
0371 const strided_iterator<
0372 OtherIterator,
0373 random_access_traversal_tag
0374 >& other,
0375 typename enable_if_convertible<
0376 OtherIterator, base_iterator>::type* = 0) const
0377 {
0378 BOOST_ASSERT((other.m_index - m_index) % m_stride == difference_type());
0379 return (other.m_index - m_index) / m_stride;
0380 }
0381
0382 template<class OtherIterator>
0383 bool equal(
0384 const strided_iterator<
0385 OtherIterator,
0386 random_access_traversal_tag
0387 >& other,
0388 typename enable_if_convertible<
0389 OtherIterator, base_iterator>::type* = 0) const
0390 {
0391 return m_index == other.m_index;
0392 }
0393
0394 reference dereference() const
0395 {
0396 update();
0397 return *m_it;
0398 }
0399
0400 private:
0401 mutable base_iterator m_it;
0402 base_iterator m_first;
0403 difference_type m_index;
0404 difference_type m_stride;
0405 };
0406
0407 template<class Rng, class Difference> inline
0408 strided_iterator<
0409 typename range_iterator<Rng>::type,
0410 forward_traversal_tag
0411 >
0412 make_begin_strided_iterator(
0413 Rng& rng,
0414 Difference stride,
0415 forward_traversal_tag)
0416 {
0417 return strided_iterator<
0418 typename range_iterator<Rng>::type,
0419 forward_traversal_tag
0420 >(boost::begin(rng), boost::end(rng), stride);
0421 }
0422
0423 template<class Rng, class Difference> inline
0424 strided_iterator<
0425 typename range_iterator<const Rng>::type,
0426 forward_traversal_tag
0427 >
0428 make_begin_strided_iterator(
0429 const Rng& rng,
0430 Difference stride,
0431 forward_traversal_tag)
0432 {
0433 return strided_iterator<
0434 typename range_iterator<const Rng>::type,
0435 forward_traversal_tag
0436 >(boost::begin(rng), boost::end(rng), stride);
0437 }
0438
0439 template<class Rng, class Difference> inline
0440 strided_iterator<
0441 typename range_iterator<Rng>::type,
0442 forward_traversal_tag
0443 >
0444 make_end_strided_iterator(
0445 Rng& rng,
0446 Difference stride,
0447 forward_traversal_tag)
0448 {
0449 return strided_iterator<
0450 typename range_iterator<Rng>::type,
0451 forward_traversal_tag
0452 >(boost::end(rng), boost::end(rng), stride);
0453 }
0454
0455 template<class Rng, class Difference> inline
0456 strided_iterator<
0457 typename range_iterator<const Rng>::type,
0458 forward_traversal_tag
0459 >
0460 make_end_strided_iterator(
0461 const Rng& rng,
0462 Difference stride,
0463 forward_traversal_tag)
0464 {
0465 return strided_iterator<
0466 typename range_iterator<const Rng>::type,
0467 forward_traversal_tag
0468 >(boost::end(rng), boost::end(rng), stride);
0469 }
0470
0471 template<class Rng, class Difference> inline
0472 strided_iterator<
0473 typename range_iterator<Rng>::type,
0474 bidirectional_traversal_tag
0475 >
0476 make_begin_strided_iterator(
0477 Rng& rng,
0478 Difference stride,
0479 bidirectional_traversal_tag)
0480 {
0481 typedef typename range_difference<Rng>::type difference_type;
0482
0483 return strided_iterator<
0484 typename range_iterator<Rng>::type,
0485 bidirectional_traversal_tag
0486 >(boost::begin(rng), difference_type(), stride);
0487 }
0488
0489 template<class Rng, class Difference> inline
0490 strided_iterator<
0491 typename range_iterator<const Rng>::type,
0492 bidirectional_traversal_tag
0493 >
0494 make_begin_strided_iterator(
0495 const Rng& rng,
0496 Difference stride,
0497 bidirectional_traversal_tag)
0498 {
0499 typedef typename range_difference<const Rng>::type difference_type;
0500
0501 return strided_iterator<
0502 typename range_iterator<const Rng>::type,
0503 bidirectional_traversal_tag
0504 >(boost::begin(rng), difference_type(), stride);
0505 }
0506
0507 template<class Rng, class Difference> inline
0508 strided_iterator<
0509 typename range_iterator<Rng>::type,
0510 bidirectional_traversal_tag
0511 >
0512 make_end_strided_iterator(
0513 Rng& rng,
0514 Difference stride,
0515 bidirectional_traversal_tag)
0516 {
0517 return strided_iterator<
0518 typename range_iterator<Rng>::type,
0519 bidirectional_traversal_tag
0520 >(boost::end(rng), boost::size(rng), stride);
0521 }
0522
0523 template<class Rng, class Difference> inline
0524 strided_iterator<
0525 typename range_iterator<const Rng>::type,
0526 bidirectional_traversal_tag
0527 >
0528 make_end_strided_iterator(
0529 const Rng& rng,
0530 Difference stride,
0531 bidirectional_traversal_tag)
0532 {
0533 return strided_iterator<
0534 typename range_iterator<const Rng>::type,
0535 bidirectional_traversal_tag
0536 >(boost::end(rng), boost::size(rng), stride);
0537 }
0538
0539 template<class Rng, class Difference> inline
0540 strided_iterator<
0541 typename range_iterator<Rng>::type,
0542 random_access_traversal_tag
0543 >
0544 make_begin_strided_iterator(
0545 Rng& rng,
0546 Difference stride,
0547 random_access_traversal_tag)
0548 {
0549 return strided_iterator<
0550 typename range_iterator<Rng>::type,
0551 random_access_traversal_tag
0552 >(boost::begin(rng), boost::begin(rng), stride);
0553 }
0554
0555 template<class Rng, class Difference> inline
0556 strided_iterator<
0557 typename range_iterator<const Rng>::type,
0558 random_access_traversal_tag
0559 >
0560 make_begin_strided_iterator(
0561 const Rng& rng,
0562 Difference stride,
0563 random_access_traversal_tag)
0564 {
0565 return strided_iterator<
0566 typename range_iterator<const Rng>::type,
0567 random_access_traversal_tag
0568 >(boost::begin(rng), boost::begin(rng), stride);
0569 }
0570
0571 template<class Rng, class Difference> inline
0572 strided_iterator<
0573 typename range_iterator<Rng>::type,
0574 random_access_traversal_tag
0575 >
0576 make_end_strided_iterator(
0577 Rng& rng,
0578 Difference stride,
0579 random_access_traversal_tag)
0580 {
0581 return strided_iterator<
0582 typename range_iterator<Rng>::type,
0583 random_access_traversal_tag
0584 >(boost::begin(rng), boost::end(rng), stride);
0585 }
0586
0587 template<class Rng, class Difference> inline
0588 strided_iterator<
0589 typename range_iterator<const Rng>::type,
0590 random_access_traversal_tag
0591 >
0592 make_end_strided_iterator(
0593 const Rng& rng,
0594 Difference stride,
0595 random_access_traversal_tag)
0596 {
0597 return strided_iterator<
0598 typename range_iterator<const Rng>::type,
0599 random_access_traversal_tag
0600 >(boost::begin(rng), boost::end(rng), stride);
0601 }
0602
0603 template<
0604 class Rng,
0605 class Category =
0606 typename iterators::pure_iterator_traversal<
0607 typename range_iterator<Rng>::type
0608 >::type
0609 >
0610 class strided_range
0611 : public iterator_range<
0612 range_detail::strided_iterator<
0613 typename range_iterator<Rng>::type,
0614 Category
0615 >
0616 >
0617 {
0618 typedef range_detail::strided_iterator<
0619 typename range_iterator<Rng>::type,
0620 Category
0621 > iter_type;
0622 typedef iterator_range<iter_type> super_t;
0623 public:
0624 template<class Difference>
0625 strided_range(Difference stride, Rng& rng)
0626 : super_t(
0627 range_detail::make_begin_strided_iterator(
0628 rng, stride,
0629 typename iterator_traversal<
0630 typename range_iterator<Rng>::type
0631 >::type()),
0632 range_detail::make_end_strided_iterator(
0633 rng, stride,
0634 typename iterator_traversal<
0635 typename range_iterator<Rng>::type
0636 >::type()))
0637 {
0638 BOOST_ASSERT( stride >= 0 );
0639 }
0640 };
0641
0642 template<class Difference>
0643 class strided_holder : public holder<Difference>
0644 {
0645 public:
0646 explicit strided_holder(Difference value)
0647 : holder<Difference>(value)
0648 {
0649 }
0650 };
0651
0652 template<class Rng, class Difference>
0653 inline strided_range<Rng>
0654 operator|(Rng& rng, const strided_holder<Difference>& stride)
0655 {
0656 return strided_range<Rng>(stride.val, rng);
0657 }
0658
0659 template<class Rng, class Difference>
0660 inline strided_range<const Rng>
0661 operator|(const Rng& rng, const strided_holder<Difference>& stride)
0662 {
0663 return strided_range<const Rng>(stride.val, rng);
0664 }
0665
0666 }
0667
0668 using range_detail::strided_range;
0669
0670 namespace adaptors
0671 {
0672
0673 namespace
0674 {
0675 const range_detail::forwarder<range_detail::strided_holder>
0676 strided = range_detail::forwarder<
0677 range_detail::strided_holder>();
0678 }
0679
0680 template<class Range, class Difference>
0681 inline strided_range<Range>
0682 stride(Range& rng, Difference step)
0683 {
0684 return strided_range<Range>(step, rng);
0685 }
0686
0687 template<class Range, class Difference>
0688 inline strided_range<const Range>
0689 stride(const Range& rng, Difference step)
0690 {
0691 return strided_range<const Range>(step, rng);
0692 }
0693
0694 }
0695 }
0696
0697 #endif