stride_iterator.hpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /* Copyright 2016-2019 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/poly_collection for library home page.
  7. */
  8. #ifndef BOOST_POLY_COLLECTION_DETAIL_STRIDE_ITERATOR_HPP
  9. #define BOOST_POLY_COLLECTION_DETAIL_STRIDE_ITERATOR_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/config.hpp>
  14. #include <boost/detail/workaround.hpp>
  15. #include <boost/iterator/iterator_facade.hpp>
  16. #include <type_traits>
  17. namespace boost{
  18. namespace poly_collection{
  19. namespace detail{
  20. /* random-access iterator to Value elements laid out stride *chars* apart */
  21. template<typename Value>
  22. class stride_iterator:
  23. public boost::iterator_facade<
  24. stride_iterator<Value>,
  25. Value,
  26. boost::random_access_traversal_tag
  27. >
  28. {
  29. public:
  30. stride_iterator()=default;
  31. stride_iterator(Value* p,std::size_t stride)noexcept:p{p},stride_{stride}{}
  32. stride_iterator(const stride_iterator&)=default;
  33. stride_iterator& operator=(const stride_iterator&)=default;
  34. template<
  35. typename NonConstValue,
  36. typename std::enable_if<
  37. std::is_same<Value,const NonConstValue>::value>::type* =nullptr
  38. >
  39. stride_iterator(const stride_iterator<NonConstValue>& x)noexcept:
  40. p{x.p},stride_{x.stride_}{}
  41. template<
  42. typename NonConstValue,
  43. typename std::enable_if<
  44. std::is_same<Value,const NonConstValue>::value>::type* =nullptr
  45. >
  46. stride_iterator& operator=(const stride_iterator<NonConstValue>& x)noexcept
  47. {
  48. p=x.p;stride_=x.stride_;
  49. return *this;
  50. }
  51. /* interoperability with [Derived]Value* */
  52. stride_iterator& operator=(Value* p_)noexcept{p=p_;return *this;}
  53. operator Value*()const noexcept{return p;}
  54. #include <boost/poly_collection/detail/begin_no_sanitize.hpp>
  55. template<
  56. typename DerivedValue,
  57. typename std::enable_if<
  58. std::is_base_of<Value,DerivedValue>::value&&
  59. (!std::is_const<Value>::value||std::is_const<DerivedValue>::value)
  60. >::type* =nullptr
  61. >
  62. BOOST_POLY_COLLECTION_NO_SANITIZE
  63. explicit operator DerivedValue*()const noexcept
  64. {return static_cast<DerivedValue*>(p);}
  65. #include <boost/poly_collection/detail/end_no_sanitize.hpp>
  66. std::size_t stride()const noexcept{return stride_;}
  67. private:
  68. template<typename>
  69. friend class stride_iterator;
  70. using char_pointer=typename std::conditional<
  71. std::is_const<Value>::value,
  72. const char*,
  73. char*
  74. >::type;
  75. static char_pointer char_ptr(Value* p)noexcept
  76. {return reinterpret_cast<char_pointer>(p);}
  77. static Value* value_ptr(char_pointer p)noexcept
  78. {return reinterpret_cast<Value*>(p);}
  79. friend class boost::iterator_core_access;
  80. Value& dereference()const noexcept{return *p;}
  81. bool equal(const stride_iterator& x)const noexcept{return p==x.p;}
  82. void increment()noexcept{p=value_ptr(char_ptr(p)+stride_);}
  83. void decrement()noexcept{p=value_ptr(char_ptr(p)-stride_);}
  84. template<typename Integral>
  85. void advance(Integral n)noexcept
  86. {p=value_ptr(char_ptr(p)+n*(std::ptrdiff_t)stride_);}
  87. std::ptrdiff_t distance_to(const stride_iterator& x)const noexcept
  88. {return (char_ptr(x.p)-char_ptr(p))/(std::ptrdiff_t)stride_;}
  89. Value* p;
  90. std::size_t stride_;
  91. };
  92. } /* namespace poly_collection::detail */
  93. } /* namespace poly_collection */
  94. } /* namespace boost */
  95. #endif