Iros
 
Loading...
Searching...
No Matches
iota_view.h
Go to the documentation of this file.
1#pragma once
2
18#include "di/math/to_unsigned.h"
19#include "di/meta/compare.h"
20#include "di/meta/core.h"
21#include "di/meta/language.h"
22#include "di/meta/operations.h"
23#include "di/meta/util.h"
24
25namespace di::container {
26namespace detail {
27 template<typename T>
28 concept IotaIncrementable = requires(T i) {
29 { ++i } -> concepts::SameAs<T&>;
30 { i++ } -> concepts::SameAs<T>;
31 };
32
33 template<typename T>
34 concept IotaDecrementable = IotaIncrementable<T> && requires(T i) {
35 { --i } -> concepts::SameAs<T&>;
36 { i-- } -> concepts::SameAs<T>;
37 };
38
39 template<typename T>
41 requires(T i, T const ci, meta::IteratorSSizeType<T> const n) {
42 { i += n } -> concepts::SameAs<T&>;
43 { i -= n } -> concepts::SameAs<T&>;
44 T(ci + n);
45 T(n + ci);
46 T(ci - n);
47 T(n - ci);
49 };
50}
51
52template<concepts::Copyable T, concepts::Semiregular Bound = UnreachableSentinel>
54 requires(T& value) {
56 ++value;
57 })
59 : public ViewInterface<IotaView<T, Bound>>
60 , public meta::EnableBorrowedContainer<IotaView<T, Bound>> {
61private:
62 using SSizeType = meta::IteratorSSizeType<T>;
63
64 constexpr static bool is_bounded = !concepts::SameAs<Bound, UnreachableSentinel>;
65
66 class Sentinel;
67
68 class Iterator
69 : public IteratorBase<
70 Iterator,
71 meta::Conditional<detail::IotaAdvancable<T>, RandomAccessIteratorTag,
72 meta::Conditional<detail::IotaDecrementable<T>, BidirectionalIteratorTag,
73 meta::Conditional<detail::IotaIncrementable<T>, ForwardIteratorTag,
74 InputIteratorTag>>>,
75 T, SSizeType> {
76 public:
77 Iterator()
79 = default;
80
81 constexpr explicit Iterator(T value) : m_value(value) {}
82
83 Iterator(Iterator const&) = default;
84 Iterator(Iterator&&) = default;
85
86 auto operator=(Iterator const&) -> Iterator& = default;
87 auto operator=(Iterator&&) -> Iterator& = default;
88
89 Iterator(Iterator const&)
91 = delete;
92
93 auto operator=(Iterator const&) -> Iterator& requires(!detail::IotaIncrementable<T>) = delete;
94
95 constexpr auto operator*() const -> T { return m_value; }
96
97 constexpr void advance_one() { ++m_value; }
98
99 constexpr void back_one()
101 {
102 --m_value;
103 }
104
105 constexpr void advance_n(SSizeType n)
107 {
108 if constexpr (concepts::UnsignedInteger<T>) {
109 if (n >= 0) {
110 m_value += static_cast<T>(n);
111 } else {
112 m_value -= static_cast<T>(-n);
113 }
114 } else {
115 m_value += n;
116 }
117 }
118
119 private:
120 friend class IotaView;
121 friend class Sentinel;
122
123 constexpr friend auto operator==(Iterator const& a, Iterator const& b) -> bool
125 {
126 return a.m_value == b.m_value;
127 }
128
129 constexpr friend auto operator<=>(Iterator const& a, Iterator const& b)
131 {
132 return a.m_value <=> b.m_value;
133 }
134
135 constexpr friend auto operator-(Iterator const& a, Iterator const& b) -> SSizeType
137 {
138 if constexpr (concepts::SignedInteger<T>) {
139 return static_cast<SSizeType>(static_cast<SSizeType>(a.m_value) - static_cast<SSizeType>(b.m_value));
140 } else if constexpr (concepts::UnsignedInteger<T>) {
141 return b.m_value > a.m_value ? static_cast<SSizeType>(-static_cast<SSizeType>(b.m_value - a.m_value))
142 : static_cast<SSizeType>(a.m_value - b.m_value);
143 } else {
144 return a.m_value - b.m_value;
145 }
146 }
147
148 public:
149 T m_value;
150 };
151
152 class Sentinel : public SentinelBase<Sentinel> {
153 public:
154 constexpr Sentinel() = default;
155 constexpr explicit Sentinel(Bound bound) : m_bound(bound) {}
156
157 constexpr auto difference(Iterator const& a) const -> SSizeType { return -(a.m_value - this->m_bound); }
158
159 private:
160 friend class IotaView;
161
162 constexpr friend auto operator==(Iterator const& a, Sentinel const& b) -> bool {
163 return a.m_value == b.m_bound;
164 }
165
166 Bound m_bound;
167 };
168
169public:
170 constexpr IotaView()
172 = default;
173
174 constexpr explicit IotaView(T value) : m_value(value) {}
175
176 constexpr IotaView(meta::TypeIdentity<T> value, meta::TypeIdentity<Bound> bound) : m_value(value), m_bound(bound) {}
177
178 constexpr IotaView(Iterator first, Iterator last)
180 : m_value(first.m_value), m_bound(last.m_value) {}
181
182 constexpr IotaView(Iterator first, Sentinel last)
183 requires(!concepts::SameAs<T, Bound> && is_bounded)
184 : m_value(first.m_value), m_bound(last.m_bound) {}
185
186 constexpr IotaView(Iterator first, UnreachableSentinel)
187 requires(!is_bounded)
188 : m_value(first.m_value) {}
189
190 constexpr auto begin() const -> Iterator { return Iterator(m_value); }
191
192 constexpr auto end() const {
193 if constexpr (is_bounded) {
194 return Sentinel(m_bound);
195 } else {
197 }
198 }
199
200 constexpr auto end() const -> Iterator
201 requires(concepts::SameAs<T, Bound>)
202 {
203 return Iterator(m_bound);
204 }
205
206 constexpr auto size() const
207 requires((concepts::SameAs<T, Bound> && detail::IotaAdvancable<T>) ||
208 (concepts::Integer<T> && concepts::Integer<Bound>) || (concepts::SizedSentinelFor<Bound, T>) )
209 {
211 if (m_value < 0) {
212 return ((m_bound < 0) ? math::to_unsigned(-m_value) - math::to_unsigned(-m_value)
213 : math::to_unsigned(m_bound) + math::to_unsigned(-m_value));
214 }
215 return math::to_unsigned(m_bound) - math::to_unsigned(m_value);
216 } else {
217 return math::to_unsigned(m_bound - m_value);
218 }
219 }
220
221private:
222 template<concepts::OneOf<Iterator, meta::Conditional<is_bounded, Sentinel, UnreachableSentinel>> Sent>
223 constexpr friend auto tag_invoke(types::Tag<container::reconstruct>, Iterator first, Sent last) {
224 if constexpr (concepts::SameAs<Iterator, Sent>) {
226 *util::move(last));
227 } else {
228 return IotaView(util::move(first), util::move(last));
229 }
230 }
231
232 T m_value {};
233 Bound m_bound {};
234};
235
236template<typename T, typename Bound>
237requires(!concepts::Integer<T> || !concepts::Integer<Bound> ||
238 concepts::SignedInteger<T> == concepts::SignedInteger<Bound>)
240}
Definition iota_view.h:60
constexpr auto size() const
Definition iota_view.h:206
constexpr IotaView(Iterator first, UnreachableSentinel)
Definition iota_view.h:186
constexpr IotaView()=default
constexpr friend auto tag_invoke(types::Tag< container::reconstruct >, Iterator first, Sent last)
Definition iota_view.h:223
constexpr IotaView(T value)
Definition iota_view.h:174
constexpr auto begin() const -> Iterator
Definition iota_view.h:190
constexpr IotaView(Iterator first, Iterator last)
Definition iota_view.h:178
constexpr IotaView(Iterator first, Sentinel last)
Definition iota_view.h:182
constexpr auto end() const
Definition iota_view.h:192
constexpr IotaView(meta::TypeIdentity< T > value, meta::TypeIdentity< Bound > bound)
Definition iota_view.h:176
constexpr auto end() const -> Iterator requires(concepts::SameAs< T, Bound >)
Definition iota_view.h:200
Definition sentinel_base.h:13
Definition view_interface.h:26
Definition operations.h:99
Definition operations.h:27
Definition compare.h:82
Definition language.h:215
Definition core.h:114
Definition language.h:241
Definition compare.h:91
Definition compare.h:103
Definition language.h:244
Definition iota_view.h:40
Definition any_storable.h:9
Definition sequence.h:13
Definition sequence.h:12
IotaView(T, Bound) -> IotaView< T, Bound >
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 unreachable_sentinel
Definition unreachable_sentinel.h:11
constexpr auto operator==(MoveIterator< Iter > const &a, MoveIterator< U > const &b) -> bool
Definition move_iterator.h:85
constexpr auto to_unsigned
Definition to_unsigned.h:16
Definition merge_interfaces.h:6
Type< TypeConstant< T > > TypeIdentity
This is a helper template to prevent C++ from deducing the type of template argument.
Definition core.h:32
decltype(container::iterator_ssize_type(types::in_place_type< meta::RemoveCVRef< T > >)) IteratorSSizeType
Definition iterator_ssize_type.h:8
di::meta::Decay< decltype(T)> Tag
Definition tag_invoke.h:28
Definition enable_borrowed_container.h:9
Definition iterator_base.h:14
Definition unreachable_sentinel.h:4