Sequoia
Loading...
Searching...
No Matches
Iterator.hpp
Go to the documentation of this file.
1
2// Copyright Oliver J. Rosten 2018. //
3// Distributed under the GNU GENERAL PUBLIC LICENSE, Version 3.0. //
4// (See accompanying file LICENSE.md or copy at //
5// https://www.gnu.org/licenses/gpl-3.0.en.html) //
7
8#pragma once
9
11
12#include <iterator>
13
18namespace sequoia::utilities
19{
20 template<class I>
21 concept decrementable = requires(I i) {
22 { --i } -> std::same_as<I&>;
23 { i-- } -> std::convertible_to<I>;
24 };
25
26 template<class I>
27 concept steppable = requires(I i, const I j, const std::iter_difference_t<I> n) {
28 { i += n } -> std::same_as<I&>;
29 { j + n } -> std::convertible_to<I>;
30 { n + j } -> std::convertible_to<I>;
31 { i -= n } -> std::same_as<I&>;
32 { j - n } -> std::convertible_to<I>;
33 };
34
35 namespace impl
36 {
37 template<class Policy>
38 struct aggregator : Policy
39 {
40 using Policy::Policy;
41
42 template<class I>
43 decltype(auto) get(I i) const
44 requires requires { static_cast<const Policy&>(*this).get(i); }
45 {
46 return Policy::get(i);
47 }
48 };
49 }
50
51 template<class Policy, class Iterator>
52 concept dereference_policy_for = requires(impl::aggregator<Policy> agg, Iterator i) {
53 typename Policy::value_type;
54 typename Policy::reference;
55
56 { agg.get(i) } -> std::same_as<typename Policy::reference>;
57 };
58
59 template<class Policy1, class Policy2>
60 inline constexpr bool consistent_policies_v{
62 };
63
66 template<class Iterator, dereference_policy_for<Iterator> Deref>
68 {
69 using type = void;
70 };
71
72 template<class Iterator, dereference_policy_for<Iterator> Deref>
73 requires requires { typename Deref::pointer; }
74 struct pointer_type<Iterator, Deref>
75 {
76 using type = typename Deref::pointer;
77 };
78
79 template<class Iterator, dereference_policy_for<Iterator> Deref>
80 using pointer_type_t = typename pointer_type<Iterator, Deref>::type;
81
84 template<class T>
85 inline constexpr bool has_difference_type{requires { typename T::difference_type; }};
86
87 template<class Iterator, dereference_policy_for<Iterator> Deref>
89
90 template<class Iterator, dereference_policy_for<Iterator> Deref>
91 requires has_difference_type<Deref>
92 struct difference_type<Iterator, Deref>
93 {
94 using type = typename Deref::difference_type;
95 };
96
97 template<class Iterator, dereference_policy_for<Iterator> Deref>
98 requires (!has_difference_type<Deref> && std::input_or_output_iterator<Iterator>)
100 {
101 using type = typename std::iterator_traits<Iterator>::difference_type;
102 };
103
104 template<class Iterator, dereference_policy_for<Iterator> Deref>
105 using difference_type_t = typename difference_type<Iterator, Deref>::type;
106
109 template<class T>
111 {
112 using type = void;
113 };
114
115 template<class I>
116 requires std::input_or_output_iterator<I>
117 struct value_type<I>
118 {
119 using type = std::iter_value_t<I>;
120 };
121
122 template<class T>
123 requires (!std::input_or_output_iterator<T> && has_value_type_v<T>)
125 {
126 using type = typename T::value_type;
127 };
128
129 template<class T>
130 using value_type_t = typename value_type<T>::type;
131
134 template<class T>
135 inline constexpr bool has_reference_type{requires { typename T::reference; }};
136
137 template<class T>
139 {
140 using type = void;
141 };
142
143 template<class I>
144 requires std::input_or_output_iterator<I>
146 {
147 using type = std::iter_reference_t<I>;
148 };
149
150 template<class T>
151 requires (!std::input_or_output_iterator<T> && has_reference_type<T>)
153 {
154 using type = typename T::reference;
155 };
156
157 template<class T>
158 using reference_type_t = typename reference_type<T>::type;
159
163 {
164 protected:
165 constexpr null_data_policy() = default;
166
167 constexpr null_data_policy(const null_data_policy&) = default;
168 constexpr null_data_policy(null_data_policy&&) noexcept = default;
169
170 ~null_data_policy() = default;
171
172 constexpr null_data_policy& operator=(const null_data_policy&) = default;
173 constexpr null_data_policy& operator=(null_data_policy&&) noexcept = default;
174
175 [[nodiscard]]
176 friend constexpr bool operator==(const null_data_policy&, const null_data_policy&) noexcept = default;
177 };
178
179 template<std::input_or_output_iterator Iterator, class AuxiliaryDataPolicy=null_data_policy>
180 struct identity_dereference_policy : public AuxiliaryDataPolicy
181 {
182 using base_iterator_type = Iterator;
183 using auxiliary_data_policy = AuxiliaryDataPolicy;
184
185 using value_type = typename std::iterator_traits<Iterator>::value_type;
186 using reference = typename std::iterator_traits<Iterator>::reference;
187 using pointer = typename std::iterator_traits<Iterator>::pointer;
188
189 template<class... Args>
190 requires (!resolve_to_copy_v<identity_dereference_policy, Args...>)
191 constexpr explicit(sizeof...(Args) == 1) identity_dereference_policy(Args&&... args)
192 : AuxiliaryDataPolicy{std::forward<Args>(args)...}
193 {}
194
196
197 [[nodiscard]]
198 constexpr static reference get(Iterator i) { return *i; }
199
200 [[nodiscard]]
201 constexpr static pointer get_ptr(Iterator i) { return &*i; }
202
203 [[nodiscard]]
204 friend constexpr bool operator==(const identity_dereference_policy&, const identity_dereference_policy&) noexcept = default;
205 protected:
206 constexpr identity_dereference_policy(identity_dereference_policy&&) noexcept = default;
207
209
210 constexpr identity_dereference_policy& operator=(const identity_dereference_policy&) = default;
211 constexpr identity_dereference_policy& operator=(identity_dereference_policy&&) noexcept = default;
212 };
213
214 template<class Iterator, dereference_policy_for<Iterator> DereferencePolicy>
215 inline constexpr bool has_sensible_semantics{
216 ( std::indirectly_writable<reference_type_t<Iterator>, value_type_t<Iterator>>
217 && std::indirectly_writable<reference_type_t<DereferencePolicy>, value_type_t<DereferencePolicy>>)
218 || ( !std::indirectly_writable<reference_type_t<Iterator>, value_type_t<Iterator>>
219 && !std::indirectly_writable<reference_type_t<DereferencePolicy>, value_type_t<DereferencePolicy>>)
220 };
221
231 template<class Iterator, dereference_policy_for<Iterator> DereferencePolicy>
232 requires has_sensible_semantics<Iterator, DereferencePolicy>
233 class iterator : public DereferencePolicy
234 {
235 public:
236 using base_iterator_type = Iterator;
237 using dereference_policy_type = DereferencePolicy;
238
239 using value_type = typename DereferencePolicy::value_type;
240 using reference = typename DereferencePolicy::reference;
241 using difference_type = difference_type_t<Iterator, DereferencePolicy>;
242 using pointer = pointer_type_t<Iterator, DereferencePolicy>;
243
244 constexpr iterator() = default;
245
246 template<class Arg, class... Args>
247 requires (!resolve_to_copy_v<iterator, Arg, Args...>)
248 constexpr explicit(sizeof...(Args) == 0) iterator(Arg&& baseIterArg, Args&&... args)
249 : DereferencePolicy{std::forward<Args>(args)...}
250 , m_BaseIterator{std::forward<Arg>(baseIterArg)}
251 {}
252
253 template<class Iter, class DerefPol>
254 requires ( !std::is_same_v<Iter, Iterator>
256 && consistent_policies_v<DereferencePolicy, DerefPol>)
257 constexpr iterator(iterator<Iter, DerefPol> iter)
258 : DereferencePolicy{static_cast<const DerefPol&>(iter)}
259 , m_BaseIterator{iter.base_iterator()}
260 {}
261
262 ~iterator() = default;
263
264 constexpr iterator(const iterator&) = default;
265 constexpr iterator(iterator&&) noexcept = default;
266 constexpr iterator& operator=(const iterator&) = default;
267 constexpr iterator& operator=(iterator&&) noexcept = default;
268
269 [[nodiscard]]
270 constexpr base_iterator_type base_iterator() const noexcept { return m_BaseIterator; }
271
272 [[nodiscard]]
273 constexpr reference operator*() const
274 {
275 return DereferencePolicy::get(m_BaseIterator);
276 }
277
278 [[nodiscard]]
279 constexpr reference operator[](const difference_type n) const
280 requires steppable<Iterator>
281 {
282 return DereferencePolicy::get(m_BaseIterator + n);
283 }
284
285 constexpr pointer operator->() const
286 requires requires (Iterator i){ DereferencePolicy::get_ptr(i); }
287 {
288 return DereferencePolicy::get_ptr(m_BaseIterator);
289 }
290
291 constexpr iterator& operator++()
292 requires std::weakly_incrementable<Iterator>
293 {
294 ++m_BaseIterator;
295 return *this;
296 }
297
298 constexpr iterator operator++(int)
299 requires std::weakly_incrementable<Iterator>
300 {
301 iterator tmp{*this};
302 operator++();
303 return tmp;
304 }
305
306 constexpr iterator& operator+=(const difference_type n)
307 requires steppable<Iterator>
308 {
309 m_BaseIterator += n;
310 return *this;
311 }
312
313 [[nodiscard]]
314 friend constexpr iterator operator+(const iterator& it, const difference_type n)
315 requires steppable<Iterator>
316 {
317 iterator tmp{it};
318 return tmp+=n;
319 }
320
321 [[nodiscard]]
322 friend constexpr iterator operator+(const difference_type n, const iterator& it)
323 requires steppable<Iterator>
324 {
325 return it + n;
326 }
327
328 constexpr iterator& operator--()
330 {
331 --m_BaseIterator; return *this;
332 }
333
334 constexpr iterator operator--(int)
336 {
337 iterator tmp{*this};
338 operator--();
339 return tmp;
340 }
341
342 constexpr iterator& operator-=(const difference_type n)
343 requires steppable<Iterator>
344 {
345 m_BaseIterator -=n;
346 return *this;
347 }
348
349 [[nodiscard]]
350 friend constexpr iterator operator-(const iterator& it, const difference_type n)
351 requires steppable<Iterator>
352 {
353 iterator tmp{it};
354 return tmp-=n;
355 }
356
357 [[nodiscard]]
358 friend constexpr difference_type operator-(const iterator& lhs, const iterator& rhs)
359 requires steppable<Iterator>
360 {
361 return lhs.base_iterator() - rhs.base_iterator();
362 }
363
364 [[nodiscard]]
365 friend constexpr bool operator==(const iterator& lhs, const iterator& rhs) noexcept
366 {
367 return lhs.m_BaseIterator == rhs.m_BaseIterator;
368 }
369
370 [[nodiscard]]
371 friend constexpr auto operator<=>(const iterator& lhs, const iterator& rhs) noexcept
372 {
373 return lhs.m_BaseIterator <=> rhs.m_BaseIterator;
374 }
375 private:
376 Iterator m_BaseIterator{};
377 };
378}
constexpr bool has_reference_type
Detects reference_type.
Definition: Iterator.hpp:135
constexpr bool has_difference_type
Detects difference_type.
Definition: Iterator.hpp:85
Traits which are sufficiently general to appear in the sequoia namespace.
An iterator with policies controlling dereferencing and auxiliary data.
Definition: Iterator.hpp:234
A concept similar to std::constructible_from, but which considers braced-init.
Definition: Concepts.hpp:75
Definition: Iterator.hpp:21
Definition: Iterator.hpp:27
Definition: Iterator.hpp:88
Definition: Iterator.hpp:39
Policy representing absence of additional data carried by theidentity_dereference_policy
Definition: Iterator.hpp:163
Detects pointer_type.
Definition: Iterator.hpp:68
Definition: Iterator.hpp:139
Detects value_type.
Definition: Iterator.hpp:111