Iros
 
Loading...
Searching...
No Matches
stride_view.h
Go to the documentation of this file.
1#pragma once
2
14#include "di/math/to_unsigned.h"
15#include "di/meta/util.h"
16
17namespace di::container {
18template<concepts::InputContainer View>
19requires(concepts::View<View>)
22 , public meta::EnableBorrowedContainer<StrideView<View>, concepts::BorrowedContainer<View>> {
23private:
24 template<bool is_const>
26
27 template<bool is_const>
29
30 template<bool is_const>
32
33 template<bool is_const>
35
36 template<bool is_const>
37 class Iterator
38 : public IteratorBase<
39 Iterator<is_const>,
40 meta::Conditional<
41 concepts::RandomAccessIterator<Iter<is_const>>, RandomAccessIteratorTag,
42 meta::Conditional<concepts::BidirectionalIterator<Iter<is_const>>, BidirectionalIteratorTag,
43 meta::Conditional<concepts::ForwardIterator<Iter<is_const>>, ForwardIteratorTag,
44 InputIteratorTag>>>,
45 ValueType<is_const>, SSizeType<is_const>> {
46 private:
47 friend class StrideView;
48
49 constexpr Iterator(meta::MaybeConst<is_const, StrideView>* parent, Iter<is_const> base,
50 SSizeType<is_const> missing = 0)
51 : m_base(util::move(base))
52 , m_end(container::end(parent->m_base))
53 , m_stride(parent->stride())
54 , m_missing(missing) {}
55
56 public:
57 Iterator()
59 = default;
60
61 constexpr Iterator(Iterator<!is_const> other)
62 requires(is_const && concepts::ConvertibleTo<Iter<false>, Iter<true>> &&
64 : m_base(util::move(other.m_base))
65 , m_end(util::move(other.m_end))
66 , m_stride(other.m_stride)
67 , m_missing(other.m_missing) {}
68
69 Iterator(Iterator const&) = default;
70 Iterator(Iterator&&) = default;
71
72 auto operator=(Iterator const&) -> Iterator& = default;
73 auto operator=(Iterator&&) -> Iterator& = default;
74
75 Iterator(Iterator const&)
77 = delete;
78 auto operator=(Iterator const&) -> Iterator& requires(!concepts::ForwardIterator<Iter<is_const>>) = delete;
79
80 constexpr auto base() && -> Iter<is_const> { return util::move(m_base); }
81 constexpr auto base() const& -> Iter<is_const> const& { return m_base; }
82
83 constexpr auto operator*() const -> decltype(auto) { return *m_base; }
84
85 constexpr void advance_one() { m_missing = container::advance(m_base, m_stride, m_end); }
86
87 constexpr void back_one()
89 {
90 container::advance(m_base, m_missing - m_stride);
91 m_missing = 0;
92 }
93
94 constexpr void advance_n(SSizeType<is_const> n)
96 {
97 if (n > 0) {
98 m_missing = container::advance(m_base, m_stride * n, m_end);
99 } else if (n < 0) {
100 container::advance(m_base, m_stride * n + m_missing);
101 m_missing = 0;
102 }
103 }
104
105 private:
106 template<bool other_is_const>
107 friend class Iterator;
108
109 constexpr friend auto operator==(Iterator const& self, DefaultSentinel) -> bool {
110 return self.m_base == self.m_end;
111 }
112 constexpr friend auto operator==(Iterator const& a, Iterator const& b) -> bool
114 {
115 return a.m_base == b.m_base;
116 }
117
118 constexpr friend auto operator<=>(Iterator const& a, Iterator const& b)
120 {
121 return a.m_base <=> b.m_base;
122 }
123
124 constexpr friend auto operator-(Iterator const& a, Iterator const& b) -> SSizeType<is_const>
125 requires(concepts::SizedSentinelFor<Iter<is_const>, Iter<is_const>>)
126 {
127 auto n = a.m_base - b.m_base;
129 return (n + a.m_missing - b.m_missing) / a.m_stride;
130 } else if (n < 0) {
131 return -math::divide_round_up(-n, a.m_stride);
132 } else {
133 return math::divide_round_up(n, a.m_stride);
134 }
135 }
136
137 constexpr friend auto operator-(DefaultSentinel, Iterator const& b) -> SSizeType<is_const> {
138 return math::divide_round_up(b.m_base - b.m_current, b.m_stride);
139 }
140 constexpr friend auto operator-(Iterator const& a, DefaultSentinel) -> SSizeType<is_const> {
141 return -(default_sentinel - a);
142 }
143
144 constexpr friend auto tag_invoke(types::Tag<container::iterator_move>, Iterator const& a)
146 return container::iterator_move(a);
147 }
148
149 constexpr friend void tag_invoke(types::Tag<container::iterator_swap>, Iterator const& a, Iterator const& b)
151 {
152 return container::iterator_swap(a, b);
153 }
154
155 Iter<is_const> m_base {};
156 Sent<is_const> m_end {};
157 SSizeType<is_const> m_stride { 0 };
158 SSizeType<is_const> m_missing { 0 };
159 };
160
161public:
162 constexpr explicit StrideView(View base, SSizeType<false> stride) : m_base(util::move(base)), m_stride(stride) {
163 DI_ASSERT(stride > 0);
164 }
165
166 constexpr auto base() const& -> View
167 requires(concepts::CopyConstructible<View>)
168 {
169 return m_base;
170 }
171 constexpr auto base() && -> View { return util::move(m_base); }
172
173 constexpr auto stride() const { return m_stride; }
174
175 constexpr auto begin()
177 {
178 return Iterator<false>(this, container::begin(m_base));
179 }
180
181 constexpr auto begin() const
182 requires(concepts::Container<View const>)
183 {
184 return Iterator<true>(this, container::begin(m_base));
185 }
186
187 constexpr auto end()
189 {
192 auto missing = (m_stride - container::distance(m_base) % m_stride) % m_stride;
193 return Iterator<false>(this, container::end(m_base), missing);
195 return Iterator<false>(this, container::end(m_base));
196 } else {
197 return default_sentinel;
198 }
199 }
200
201 constexpr auto end() const
202 requires(concepts::Container<View const>)
203 {
206 auto missing = (m_stride - container::distance(m_base) % m_stride) % m_stride;
207 return Iterator<true>(this, container::end(m_base), missing);
209 return Iterator<true>(this, container::end(m_base));
210 } else {
211 return default_sentinel;
212 }
213 }
214
215 constexpr auto size()
217 {
219 }
220
221 constexpr auto size() const
222 requires(concepts::SizedContainer<View const>)
223 {
225 }
226
227private:
228 View m_base;
229 SSizeType<false> m_stride;
230};
231
232template<typename Con>
234}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition stride_view.h:22
constexpr auto stride() const
Definition stride_view.h:173
constexpr auto base() &&-> View
Definition stride_view.h:171
constexpr auto end() const
Definition stride_view.h:201
constexpr auto size()
Definition stride_view.h:215
constexpr auto end()
Definition stride_view.h:187
constexpr auto size() const
Definition stride_view.h:221
constexpr auto begin() const
Definition stride_view.h:181
constexpr auto base() const &-> View requires(concepts::CopyConstructible< View >)
Definition stride_view.h:166
constexpr StrideView(View base, SSizeType< false > stride)
Definition stride_view.h:162
constexpr auto begin()
Definition stride_view.h:175
Definition view_interface.h:26
Definition view.h:35
constexpr friend auto tag_invoke(types::Tag< container::enable_borrowed_container >, types::InPlaceType< StrideView< View > >) -> bool
Definition enable_borrowed_container.h:9
Definition bidirectional_container.h:8
Definition bidirectional_iterator.h:8
Definition common_container.h:10
Definition operations.h:99
Definition operations.h:27
Definition compare.h:82
Definition forward_container.h:8
Definition forward_iterator.h:10
Definition indirectly_swappable.h:7
Definition random_access_iterator.h:12
Definition simple_view.h:11
Definition sized_container.h:8
Definition sized_sentinel_for.h:9
Definition any_storable.h:9
Definition sequence.h:12
constexpr auto operator<=>(MoveIterator< Iter > const &a, MoveIterator< U > const &b)
Definition move_iterator.h:90
constexpr auto operator-(MoveIterator< Iter > const &a, MoveIterator< U > const &b) -> decltype(a.base() - b.base())
Definition move_iterator.h:95
constexpr auto iterator_move
Definition iterator_move.h:56
constexpr auto move
Definition move.h:38
StrideView(Con &&, meta::ContainerSSizeType< Con >) -> StrideView< meta::AsView< Con > >
constexpr auto operator==(MoveIterator< Iter > const &a, MoveIterator< U > const &b) -> bool
Definition move_iterator.h:85
constexpr auto distance
Definition distance.h:44
constexpr auto iterator_swap
Definition iterator_swap.h:49
constexpr auto default_sentinel
Definition default_sentinel.h:6
constexpr auto end
Definition end.h:47
constexpr auto advance
Definition advance.h:62
constexpr auto begin
Definition begin.h:44
constexpr auto to_unsigned
Definition to_unsigned.h:16
constexpr auto divide_round_up
Definition divide_round_up.h:17
Definition merge_interfaces.h:6
IteratorSSizeType< ContainerIterator< T > > ContainerSSizeType
Definition container_ssize_type.h:8
IteratorRValue< ContainerIterator< T > > ContainerRValue
Definition container_rvalue.h:8
decltype(container::end(util::declval< T & >())) ContainerSentinel
Definition container_sentinel.h:8
Conditional< is_const, T const, T > MaybeConst
Definition util.h:9
IteratorValue< ContainerIterator< T > > ContainerValue
Definition container_value.h:8
decltype(container::begin(util::declval< T & >())) ContainerIterator
Definition container_iterator.h:8
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
Definition vocab.h:96
Definition default_sentinel.h:4
Definition enable_borrowed_container.h:9
Definition iterator_base.h:14