File indexing completed on 2025-01-18 09:47:50
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_POLY_COLLECTION_DETAIL_STRIDE_ITERATOR_HPP
0010 #define BOOST_POLY_COLLECTION_DETAIL_STRIDE_ITERATOR_HPP
0011
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015
0016 #include <boost/detail/workaround.hpp>
0017 #include <boost/iterator/iterator_facade.hpp>
0018 #include <type_traits>
0019
0020 namespace boost{
0021
0022 namespace poly_collection{
0023
0024 namespace detail{
0025
0026
0027
0028 template<typename Value>
0029 class stride_iterator:
0030 public boost::iterator_facade<
0031 stride_iterator<Value>,
0032 Value,
0033 boost::random_access_traversal_tag
0034 >
0035 {
0036 public:
0037 stride_iterator()=default;
0038 stride_iterator(Value* p,std::size_t stride)noexcept:p{p},stride_{stride}{}
0039 stride_iterator(const stride_iterator&)=default;
0040 stride_iterator& operator=(const stride_iterator&)=default;
0041
0042 template<
0043 typename NonConstValue,
0044 typename std::enable_if<
0045 std::is_same<Value,const NonConstValue>::value>::type* =nullptr
0046 >
0047 stride_iterator(const stride_iterator<NonConstValue>& x)noexcept:
0048 p{x.p},stride_{x.stride_}{}
0049
0050 template<
0051 typename NonConstValue,
0052 typename std::enable_if<
0053 std::is_same<Value,const NonConstValue>::value>::type* =nullptr
0054 >
0055 stride_iterator& operator=(const stride_iterator<NonConstValue>& x)noexcept
0056 {
0057 p=x.p;stride_=x.stride_;
0058 return *this;
0059 }
0060
0061
0062
0063 stride_iterator& operator=(Value* p_)noexcept{p=p_;return *this;}
0064 operator Value*()const noexcept{return p;}
0065
0066 template<
0067 typename DerivedValue,
0068 typename std::enable_if<
0069 std::is_base_of<Value,DerivedValue>::value&&
0070 (std::is_const<Value>::value||!std::is_const<DerivedValue>::value)
0071 >::type* =nullptr
0072 >
0073 explicit stride_iterator(DerivedValue* x)noexcept:
0074 p{x},stride_{sizeof(DerivedValue)}{}
0075
0076 #if BOOST_WORKAROUND(BOOST_GCC_VERSION,>=40900)||\
0077 BOOST_WORKAROUND(BOOST_CLANG,>=1)&&\
0078 (__clang_major__>3 || __clang_major__==3 && __clang_minor__ >= 8)
0079
0080
0081 #define BOOST_POLY_COLLECTION_NO_SANITIZE
0082
0083
0084 #if defined(BOOST_GCC_VERSION)
0085 #pragma GCC diagnostic push
0086 #pragma GCC diagnostic ignored "-Wattributes"
0087 #elif defined(BOOST_CLANG)
0088 #pragma clang diagnostic push
0089 #pragma clang diagnostic ignored "-Wattributes"
0090 #endif
0091 #endif
0092
0093 template<
0094 typename DerivedValue,
0095 typename std::enable_if<
0096 std::is_base_of<Value,DerivedValue>::value&&
0097 (!std::is_const<Value>::value||std::is_const<DerivedValue>::value)
0098 >::type* =nullptr
0099 >
0100 #if defined(BOOST_POLY_COLLECTION_NO_SANITIZE)
0101 __attribute__((no_sanitize("undefined")))
0102 #endif
0103 explicit operator DerivedValue*()const noexcept
0104 {return static_cast<DerivedValue*>(p);}
0105
0106 #if defined(BOOST_POLY_COLLECTION_NO_SANITIZE)
0107 #if defined(BOOST_GCC_VERSION)
0108 #pragma GCC diagnostic pop
0109 #elif defined(BOOST_CLANG)
0110 #pragma clang diagnostic pop
0111 #endif
0112
0113 #undef BOOST_POLY_COLLECTION_NO_SANITIZE
0114 #endif
0115
0116 std::size_t stride()const noexcept{return stride_;}
0117
0118 private:
0119 template<typename>
0120 friend class stride_iterator;
0121
0122 using char_pointer=typename std::conditional<
0123 std::is_const<Value>::value,
0124 const char*,
0125 char*
0126 >::type;
0127
0128 static char_pointer char_ptr(Value* p)noexcept
0129 {return reinterpret_cast<char_pointer>(p);}
0130 static Value* value_ptr(char_pointer p)noexcept
0131 {return reinterpret_cast<Value*>(p);}
0132
0133 friend class boost::iterator_core_access;
0134
0135 Value& dereference()const noexcept{return *p;}
0136 bool equal(const stride_iterator& x)const noexcept{return p==x.p;}
0137 void increment()noexcept{p=value_ptr(char_ptr(p)+stride_);}
0138 void decrement()noexcept{p=value_ptr(char_ptr(p)-stride_);}
0139 template<typename Integral>
0140 void advance(Integral n)noexcept
0141 {p=value_ptr(char_ptr(p)+n*(std::ptrdiff_t)stride_);}
0142 std::ptrdiff_t distance_to(const stride_iterator& x)const noexcept
0143 {return (char_ptr(x.p)-char_ptr(p))/(std::ptrdiff_t)stride_;}
0144
0145 Value* p;
0146 std::size_t stride_;
0147 };
0148
0149 }
0150
0151 }
0152
0153 }
0154
0155 #endif