di 0.1.0
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>
40 concept IotaAdvancable = IotaDecrementable<T> && concepts::TotallyOrdered<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);
48 { ci - ci } -> concepts::ConvertibleTo<meta::IteratorSSizeType<T>>;
49 };
50}
51
52template<concepts::Copyable T, concepts::Semiregular Bound = UnreachableSentinel>
53requires(concepts::detail::WeaklyEqualityComparableWith<T, Bound> &&
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&)
90 requires(!detail::IotaIncrementable<T>)
91 = delete;
92
93 auto operator=(Iterator const&) -> Iterator&
94 requires(!detail::IotaIncrementable<T>)
95 = delete;
96
97 constexpr auto operator*() const -> T { return m_value; }
98
99 constexpr void advance_one() { ++m_value; }
100
101 constexpr void back_one()
102 requires(detail::IotaDecrementable<T>)
103 {
104 --m_value;
105 }
106
107 constexpr void advance_n(SSizeType n)
108 requires(detail::IotaAdvancable<T>)
109 {
110 if constexpr (concepts::UnsignedInteger<T>) {
111 if (n >= 0) {
112 m_value += static_cast<T>(n);
113 } else {
114 m_value -= static_cast<T>(-n);
115 }
116 } else {
117 m_value += n;
118 }
119 }
120
121 private:
122 friend class IotaView;
123 friend class Sentinel;
124
125 constexpr friend auto operator==(Iterator const& a, Iterator const& b) -> bool
127 {
128 return a.m_value == b.m_value;
129 }
130
131 constexpr friend auto operator<=>(Iterator const& a, Iterator const& b)
133 {
134 return a.m_value <=> b.m_value;
135 }
136
137 constexpr friend auto operator-(Iterator const& a, Iterator const& b) -> SSizeType
138 requires(detail::IotaAdvancable<T>)
139 {
140 if constexpr (concepts::SignedInteger<T>) {
141 return static_cast<SSizeType>(static_cast<SSizeType>(a.m_value) - static_cast<SSizeType>(b.m_value));
142 } else if constexpr (concepts::UnsignedInteger<T>) {
143 return b.m_value > a.m_value ? static_cast<SSizeType>(-static_cast<SSizeType>(b.m_value - a.m_value))
144 : static_cast<SSizeType>(a.m_value - b.m_value);
145 } else {
146 return a.m_value - b.m_value;
147 }
148 }
149
150 public:
151 T m_value;
152 };
153
154 class Sentinel : public SentinelBase<Sentinel> {
155 public:
156 constexpr Sentinel() = default;
157 constexpr explicit Sentinel(Bound bound) : m_bound(bound) {}
158
159 constexpr auto difference(Iterator const& a) const -> SSizeType { return -(a.m_value - this->m_bound); }
160
161 private:
162 friend class IotaView;
163
164 constexpr friend auto operator==(Iterator const& a, Sentinel const& b) -> bool {
165 return a.m_value == b.m_bound;
166 }
167
168 Bound m_bound;
169 };
170
171public:
172 constexpr IotaView()
174 = default;
175
176 constexpr explicit IotaView(T value) : m_value(value) {}
177
178 constexpr IotaView(meta::TypeIdentity<T> value, meta::TypeIdentity<Bound> bound) : m_value(value), m_bound(bound) {}
179
180 constexpr IotaView(Iterator first, Iterator last)
182 : m_value(first.m_value), m_bound(last.m_value) {}
183
184 constexpr IotaView(Iterator first, Sentinel last)
185 requires(!concepts::SameAs<T, Bound> && is_bounded)
186 : m_value(first.m_value), m_bound(last.m_bound) {}
187
188 constexpr IotaView(Iterator first, UnreachableSentinel)
189 requires(!is_bounded)
190 : m_value(first.m_value) {}
191
192 constexpr auto begin() const -> Iterator { return Iterator(m_value); }
193
194 constexpr auto end() const {
195 if constexpr (is_bounded) {
196 return Sentinel(m_bound);
197 } else {
199 }
200 }
201
202 constexpr auto end() const -> Iterator
203 requires(concepts::SameAs<T, Bound>)
204 {
205 return Iterator(m_bound);
206 }
207
208 constexpr auto size() const
209 requires((concepts::SameAs<T, Bound> && detail::IotaAdvancable<T>) ||
210 (concepts::Integer<T> && concepts::Integer<Bound>) || (concepts::SizedSentinelFor<Bound, T>) )
211 {
213 if (m_value < 0) {
214 return ((m_bound < 0) ? math::to_unsigned(-m_value) - math::to_unsigned(-m_value)
215 : math::to_unsigned(m_bound) + math::to_unsigned(-m_value));
216 }
217 return math::to_unsigned(m_bound) - math::to_unsigned(m_value);
218 } else {
219 return math::to_unsigned(m_bound - m_value);
220 }
221 }
222
223private:
224 template<concepts::OneOf<Iterator, meta::Conditional<is_bounded, Sentinel, UnreachableSentinel>> Sent>
225 constexpr friend auto tag_invoke(types::Tag<container::reconstruct>, Iterator first, Sent last) {
226 if constexpr (concepts::SameAs<Iterator, Sent>) {
228 *util::move(last));
229 } else {
230 return IotaView(util::move(first), util::move(last));
231 }
232 }
233
234 T m_value {};
235 Bound m_bound {};
236};
237
238template<typename T, typename Bound>
239requires(!concepts::Integer<T> || !concepts::Integer<Bound> ||
240 concepts::SignedInteger<T> == concepts::SignedInteger<Bound>)
242}
Definition iota_view.h:60
constexpr auto size() const
Definition iota_view.h:208
constexpr IotaView(Iterator first, UnreachableSentinel)
Definition iota_view.h:188
constexpr IotaView()=default
constexpr friend auto tag_invoke(types::Tag< container::reconstruct >, Iterator first, Sent last)
Definition iota_view.h:225
constexpr IotaView(T value)
Definition iota_view.h:176
constexpr auto begin() const -> Iterator
Definition iota_view.h:192
constexpr IotaView(Iterator first, Iterator last)
Definition iota_view.h:180
constexpr IotaView(Iterator first, Sentinel last)
Definition iota_view.h:184
constexpr auto end() const
Definition iota_view.h:194
constexpr IotaView(meta::TypeIdentity< T > value, meta::TypeIdentity< Bound > bound)
Definition iota_view.h:178
constexpr auto end() const -> Iterator requires(concepts::SameAs< T, Bound >)
Definition iota_view.h:202
Definition sentinel_base.h:13
Definition view_interface.h:26
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 language.h:244
Definition any_storable.h:9
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 value
Definition value.h:34
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