di 0.1.0
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&
80 = delete;
81
82 constexpr auto base() && -> Iter<is_const> { return util::move(m_base); }
83 constexpr auto base() const& -> Iter<is_const> const& { return m_base; }
84
85 constexpr auto operator*() const -> decltype(auto) { return *m_base; }
86
87 constexpr void advance_one() { m_missing = container::advance(m_base, m_stride, m_end); }
88
89 constexpr void back_one()
91 {
92 container::advance(m_base, m_missing - m_stride);
93 m_missing = 0;
94 }
95
96 constexpr void advance_n(SSizeType<is_const> n)
98 {
99 if (n > 0) {
100 m_missing = container::advance(m_base, m_stride * n, m_end);
101 } else if (n < 0) {
102 container::advance(m_base, m_stride * n + m_missing);
103 m_missing = 0;
104 }
105 }
106
107 private:
108 template<bool other_is_const>
109 friend class Iterator;
110
111 constexpr friend auto operator==(Iterator const& self, DefaultSentinel) -> bool {
112 return self.m_base == self.m_end;
113 }
114 constexpr friend auto operator==(Iterator const& a, Iterator const& b) -> bool
116 {
117 return a.m_base == b.m_base;
118 }
119
120 constexpr friend auto operator<=>(Iterator const& a, Iterator const& b)
122 {
123 return a.m_base <=> b.m_base;
124 }
125
126 constexpr friend auto operator-(Iterator const& a, Iterator const& b) -> SSizeType<is_const>
127 requires(concepts::SizedSentinelFor<Iter<is_const>, Iter<is_const>>)
128 {
129 auto n = a.m_base - b.m_base;
131 return (n + a.m_missing - b.m_missing) / a.m_stride;
132 } else if (n < 0) {
133 return -math::divide_round_up(-n, a.m_stride);
134 } else {
135 return math::divide_round_up(n, a.m_stride);
136 }
137 }
138
139 constexpr friend auto operator-(DefaultSentinel, Iterator const& b) -> SSizeType<is_const> {
140 return math::divide_round_up(b.m_base - b.m_current, b.m_stride);
141 }
142 constexpr friend auto operator-(Iterator const& a, DefaultSentinel) -> SSizeType<is_const> {
143 return -(default_sentinel - a);
144 }
145
146 constexpr friend auto tag_invoke(types::Tag<container::iterator_move>, Iterator const& a)
148 return container::iterator_move(a);
149 }
150
151 constexpr friend void tag_invoke(types::Tag<container::iterator_swap>, Iterator const& a, Iterator const& b)
153 {
154 return container::iterator_swap(a, b);
155 }
156
157 Iter<is_const> m_base {};
158 Sent<is_const> m_end {};
159 SSizeType<is_const> m_stride { 0 };
160 SSizeType<is_const> m_missing { 0 };
161 };
162
163public:
164 constexpr explicit StrideView(View base, SSizeType<false> stride) : m_base(util::move(base)), m_stride(stride) {
165 DI_ASSERT(stride > 0);
166 }
167
168 constexpr auto base() const& -> View
169 requires(concepts::CopyConstructible<View>)
170 {
171 return m_base;
172 }
173 constexpr auto base() && -> View { return util::move(m_base); }
174
175 constexpr auto stride() const { return m_stride; }
176
177 constexpr auto begin()
179 {
180 return Iterator<false>(this, container::begin(m_base));
181 }
182
183 constexpr auto begin() const
184 requires(concepts::Container<View const>)
185 {
186 return Iterator<true>(this, container::begin(m_base));
187 }
188
189 constexpr auto end()
191 {
194 auto missing = (m_stride - container::distance(m_base) % m_stride) % m_stride;
195 return Iterator<false>(this, container::end(m_base), missing);
197 return Iterator<false>(this, container::end(m_base));
198 } else {
199 return default_sentinel;
200 }
201 }
202
203 constexpr auto end() const
204 requires(concepts::Container<View const>)
205 {
208 auto missing = (m_stride - container::distance(m_base) % m_stride) % m_stride;
209 return Iterator<true>(this, container::end(m_base), missing);
211 return Iterator<true>(this, container::end(m_base));
212 } else {
213 return default_sentinel;
214 }
215 }
216
217 constexpr auto size()
219 {
221 }
222
223 constexpr auto size() const
224 requires(concepts::SizedContainer<View const>)
225 {
227 }
228
229private:
230 View m_base;
231 SSizeType<false> m_stride;
232};
233
234template<typename Con>
236}
#define DI_ASSERT(...)
Definition assert_bool.h:7
Definition stride_view.h:22
constexpr auto stride() const
Definition stride_view.h:175
constexpr auto base() &&-> View
Definition stride_view.h:173
constexpr auto end() const
Definition stride_view.h:203
constexpr auto size()
Definition stride_view.h:217
constexpr auto end()
Definition stride_view.h:189
constexpr auto size() const
Definition stride_view.h:223
constexpr auto begin() const
Definition stride_view.h:183
constexpr auto base() const &-> View requires(concepts::CopyConstructible< View >)
Definition stride_view.h:168
constexpr StrideView(View base, SSizeType< false > stride)
Definition stride_view.h:164
constexpr auto begin()
Definition stride_view.h:177
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:55
constexpr auto advance
Definition advance.h:62
constexpr auto begin
Definition begin.h:52
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