stride_iterator.hpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. /* Copyright 2016-2017 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/iterator/iterator_facade.hpp>
  14. #include <type_traits>
  15. namespace boost{
  16. namespace poly_collection{
  17. namespace detail{
  18. /* random-access iterator to Value elements laid out stride *chars* apart */
  19. template<typename Value>
  20. class stride_iterator:
  21. public boost::iterator_facade<
  22. stride_iterator<Value>,
  23. Value,
  24. boost::random_access_traversal_tag
  25. >
  26. {
  27. public:
  28. stride_iterator()=default;
  29. stride_iterator(Value* p,std::size_t stride)noexcept:p{p},stride_{stride}{}
  30. stride_iterator(const stride_iterator&)=default;
  31. stride_iterator& operator=(const stride_iterator&)=default;
  32. template<
  33. typename NonConstValue,
  34. typename std::enable_if<
  35. std::is_same<Value,const NonConstValue>::value>::type* =nullptr
  36. >
  37. stride_iterator(const stride_iterator<NonConstValue>& x)noexcept:
  38. p{x.p},stride_{x.stride_}{}
  39. template<
  40. typename NonConstValue,
  41. typename std::enable_if<
  42. std::is_same<Value,const NonConstValue>::value>::type* =nullptr
  43. >
  44. stride_iterator& operator=(const stride_iterator<NonConstValue>& x)noexcept
  45. {
  46. p=x.p;stride_=x.stride_;
  47. return *this;
  48. }
  49. /* interoperability with [Derived]Value* */
  50. stride_iterator& operator=(Value* p_)noexcept{p=p_;return *this;}
  51. operator Value*()const noexcept{return p;}
  52. template<
  53. typename DerivedValue,
  54. typename std::enable_if<
  55. std::is_base_of<Value,DerivedValue>::value&&
  56. (std::is_const<Value>::value||!std::is_const<DerivedValue>::value)
  57. >::type* =nullptr
  58. >
  59. explicit stride_iterator(DerivedValue* x)noexcept:
  60. p{x},stride_{sizeof(DerivedValue)}{}
  61. template<
  62. typename DerivedValue,
  63. typename std::enable_if<
  64. std::is_base_of<Value,DerivedValue>::value&&
  65. (!std::is_const<Value>::value||std::is_const<DerivedValue>::value)
  66. >::type* =nullptr
  67. >
  68. explicit operator DerivedValue*()const noexcept
  69. {return static_cast<DerivedValue*>(p);}
  70. std::size_t stride()const noexcept{return stride_;}
  71. private:
  72. template<typename>
  73. friend class stride_iterator;
  74. using char_pointer=typename std::conditional<
  75. std::is_const<Value>::value,
  76. const char*,
  77. char*
  78. >::type;
  79. static char_pointer char_ptr(Value* p)noexcept
  80. {return reinterpret_cast<char_pointer>(p);}
  81. static Value* value_ptr(char_pointer p)noexcept
  82. {return reinterpret_cast<Value*>(p);}
  83. friend class boost::iterator_core_access;
  84. Value& dereference()const noexcept{return *p;}
  85. bool equal(const stride_iterator& x)const noexcept{return p==x.p;}
  86. void increment()noexcept{p=value_ptr(char_ptr(p)+stride_);}
  87. void decrement()noexcept{p=value_ptr(char_ptr(p)-stride_);}
  88. template<typename Integral>
  89. void advance(Integral n)noexcept
  90. {p=value_ptr(char_ptr(p)+n*(std::ptrdiff_t)stride_);}
  91. std::ptrdiff_t distance_to(const stride_iterator& x)const noexcept
  92. {return (char_ptr(x.p)-char_ptr(p))/(std::ptrdiff_t)stride_;}
  93. Value* p;
  94. std::size_t stride_;
  95. };
  96. } /* namespace poly_collection::detail */
  97. } /* namespace poly_collection */
  98. } /* namespace boost */
  99. #endif