Iros
 
Loading...
Searching...
No Matches
zip_view.h
Go to the documentation of this file.
1#pragma once
2
13#include "di/meta/common.h"
14#include "di/meta/operations.h"
15#include "di/meta/util.h"
16#include "di/util/move.h"
18
19namespace di::container {
20template<concepts::InputContainer... Views>
21requires((concepts::View<Views> && ...) && sizeof...(Views) > 0)
23 : public ViewInterface<ZipView<Views...>>
24 , public meta::EnableBorrowedContainer<ZipView<Views...>, (concepts::BorrowedContainer<Views> && ...)> {
25private:
26 constexpr static bool all_simple = (concepts::SimpleView<Views> && ...);
27 constexpr static bool all_const = (concepts::Container<Views const> && ...);
28
29 template<bool is_const>
30 constexpr static bool all_sized = (concepts::SizedContainer<meta::MaybeConst<is_const, Views>> && ...);
31
32 template<bool is_const>
33 constexpr static bool all_forward = (concepts::ForwardContainer<meta::MaybeConst<is_const, Views>> && ...);
34
35 template<bool is_const>
36 constexpr static bool all_bidirectional =
38
39 template<bool is_const>
40 constexpr static bool all_random_access =
42
43 template<bool is_const>
44 constexpr static bool all_common = (concepts::CommonContainer<meta::MaybeConst<is_const, Views>> && ...);
45
46 template<bool is_const>
47 constexpr static bool is_common =
48 (sizeof...(Views) == 1 && all_common<is_const>) || (!all_bidirectional<is_const> && all_common<is_const>) ||
49 (all_random_access<is_const> && all_sized<is_const>);
50
51 template<bool is_const>
53
54 template<bool is_const>
56
57 template<bool is_const>
58 class Sentinel;
59
60 template<bool is_const>
61 class Iterator
62 : public IteratorBase<
63 Iterator<is_const>,
64 meta::Conditional<
65 all_random_access<is_const>, RandomAccessIteratorTag,
66 meta::Conditional<all_bidirectional<is_const>, BidirectionalIteratorTag,
67 meta::Conditional<all_forward<is_const>, ForwardIteratorTag, InputIteratorTag>>>,
68 Value<is_const>, SSizeType<is_const>> {
69 private:
71
72 constexpr explicit Iterator(Storage iterators) : m_iterators(util::move(iterators)) {}
73
74 template<bool is_const_>
75 friend class Sentinel;
76
77 friend class ZipView;
78
79 public:
80 Iterator() = default;
81
82 constexpr Iterator(Iterator<!is_const> other)
85 ...))
86 : m_iterators(util::move(other)) {}
87
88 Iterator(Iterator const&) = default;
89 Iterator(Iterator&&) = default;
90
91 auto operator=(Iterator const&) -> Iterator& = default;
92 auto operator=(Iterator&&) -> Iterator& = default;
93
94 Iterator(Iterator const&)
95 requires(!all_forward<is_const>)
96 = delete;
97 auto operator=(Iterator const&) -> Iterator& requires(!all_forward<is_const>) = delete;
98
99 constexpr auto operator*() const {
100 return tuple_transform(
101 [](auto& iterator) -> decltype(*iterator) {
102 return *iterator;
103 },
104 m_iterators);
105 }
106
107 constexpr void advance_one() {
109 [](auto& iterator) {
110 ++iterator;
111 },
112 m_iterators);
113 }
114
115 constexpr void back_one()
116 requires(all_bidirectional<is_const>)
117 {
119 [](auto& iterator) {
120 --iterator;
121 },
122 m_iterators);
123 }
124
125 constexpr void advance_n(SSizeType<is_const> n)
126 requires(all_random_access<is_const>)
127 {
129 [&](auto& iterator) {
130 iterator += n;
131 },
132 m_iterators);
133 }
134
135 constexpr auto iterators() const -> Storage const& { return m_iterators; }
136
137 private:
138 constexpr friend auto operator==(Iterator const& a, Iterator const& b) -> bool
140 {
141 if constexpr (all_bidirectional<is_const>) {
142 return a.m_iterators == b.m_iterators;
143 } else {
144 return function::unpack<meta::MakeIndexSequence<sizeof...(Views)>>(
145 [&]<size_t... indices>(meta::ListV<indices...>) {
146 return ((util::get<indices>(a.m_iterators) <= util::get<indices>(b.m_iterators)) || ...);
147 });
148 }
149 }
150
151 constexpr friend auto operator<=>(Iterator const& a, Iterator const& b)
152 requires(all_random_access<is_const> &&
154 {
155 return a.m_iterators <=> b.m_iterators;
156 }
157
158 constexpr friend auto operator-(Iterator const& a, Iterator const& b) -> SSizeType<is_const>
161 ...)
162 {
163 return function::unpack<meta::MakeIndexSequence<sizeof...(Views)>>(
164 [&]<size_t... indices>(meta::ListV<indices...>) {
165 return container::min({ static_cast<SSizeType<is_const>>(util::get<indices>(a.m_iterators) -
166 util::get<indices>(b.m_iterators))... });
167 });
168 }
169
170 constexpr friend auto tag_invoke(types::Tag<iterator_move>, Iterator const& self) {
171 return tuple_transform(iterator_move, self.m_iterators);
172 }
173
174 constexpr friend void tag_invoke(types::Tag<iterator_swap>, Iterator const& a, Iterator const& b)
177 ...)
178 {
179 return function::unpack<meta::MakeIndexSequence<sizeof...(Views)>>(
180 [&]<size_t... indices>(meta::ListV<indices...>) {
181 (void) (iterator_swap(util::get<indices>(a.m_iterators), util::get<indices>(b.m_iterators)), ...);
182 });
183 }
184
185 Storage m_iterators;
186 };
187
188 template<bool is_const>
189 class Sentinel : public SentinelBase<Sentinel<is_const>> {
190 private:
192
193 constexpr explicit Sentinel(Storage sentinels) : m_sentinels(util::move(sentinels)) {}
194
195 friend class ZipView;
196
197 public:
198 Sentinel() = default;
199
200 constexpr Sentinel(Sentinel<!is_const> other)
203 ...))
204 : m_sentinels(util::move(other)) {}
205
206 template<bool other_is_const>
209 ...)
210 constexpr auto difference(Iterator<other_is_const> const& a) const {
211 return function::unpack<meta::MakeIndexSequence<sizeof...(Views)>>(
212 [&]<size_t... indices>(meta::ListV<indices...>) {
213 return container::min({ static_cast<SSizeType<is_const>>(util::get<indices>(this->m_sentinels) -
214 util::get<indices>(a.m_iterators))... });
215 });
216 }
217
218 private:
219 template<bool other_is_const>
222 ...)
223 constexpr friend auto operator==(Iterator<other_is_const> const& a, Sentinel const& b) -> bool {
224 return function::unpack<meta::MakeIndexSequence<sizeof...(Views)>>(
225 [&]<size_t... indices>(meta::ListV<indices...>) {
226 return ((util::get<indices>(a.m_iterators) == util::get<indices>(b.m_sentinels)) || ...);
227 });
228 }
229
230 Storage m_sentinels;
231 };
232
233public:
234 ZipView() = default;
235
238 = delete;
239
240 constexpr explicit ZipView(Views... views) : m_views(util::move(views)...) {}
241
242 constexpr auto begin()
243 requires(!all_simple)
244 {
245 return Iterator<false>(tuple_transform(container::begin, m_views));
246 }
247
248 constexpr auto begin() const
249 requires(all_const)
250 {
251 return Iterator<true>(tuple_transform(container::begin, m_views));
252 }
253
254 constexpr auto end()
255 requires(!all_simple)
256 {
257 if constexpr (!is_common<false>) {
258 return Sentinel<false>(tuple_transform(container::end, m_views));
259 } else if constexpr (all_random_access<false>) {
260 return begin() + static_cast<SSizeType<false>>(size());
261 } else {
262 return Iterator<false>(tuple_transform(container::end, m_views));
263 }
264 }
265
266 constexpr auto end() const
267 requires(all_const)
268 {
269 if constexpr (!is_common<true>) {
270 return Sentinel<true>(tuple_transform(container::end, m_views));
271 } else if constexpr (all_random_access<true>) {
272 return begin() + static_cast<SSizeType<true>>(size());
273 } else {
274 return Iterator<true>(tuple_transform(container::end, m_views));
275 }
276 }
277
278 constexpr auto size()
279 requires(all_sized<false>)
280 {
281 return apply(
282 [](auto... sizes) {
283 using CommonType = meta::MakeUnsigned<meta::CommonType<decltype(sizes)...>>;
284 return container::min({ static_cast<CommonType>(sizes)... });
285 },
287 }
288
289 constexpr auto size() const
290 requires(all_sized<true>)
291 {
292 return apply(
293 [](auto... sizes) {
294 using CommonType = meta::MakeUnsigned<meta::CommonType<decltype(sizes)...>>;
295 return container::min({ static_cast<CommonType>(sizes)... });
296 },
298 }
299
300private:
301 Tuple<Views...> m_views;
302};
303
304template<typename... Cons>
306}
Definition sentinel_base.h:13
Definition view_interface.h:26
Definition zip_view.h:24
constexpr auto end()
Definition zip_view.h:254
constexpr auto size() const
Definition zip_view.h:289
constexpr ZipView(Views... views)
Definition zip_view.h:240
constexpr auto end() const
Definition zip_view.h:266
constexpr auto begin()
Definition zip_view.h:242
constexpr auto size()
Definition zip_view.h:278
constexpr auto begin() const
Definition zip_view.h:248
constexpr friend auto tag_invoke(types::Tag< container::enable_borrowed_container >, types::InPlaceType< ZipView< Views... > >) -> bool
Definition enable_borrowed_container.h:9
Definition tuple_forward_declaration.h:5
Definition bidirectional_container.h:8
Definition common_container.h:10
Definition container.h:8
Definition operations.h:99
Definition operations.h:24
Definition compare.h:82
Definition forward_container.h:8
Definition indirectly_swappable.h:7
Definition random_access_container.h:8
Definition sentinel_for.h:9
Definition simple_view.h:11
Definition sized_container.h:8
Definition sized_sentinel_for.h:9
Definition compare.h:91
Definition any_storable.h:9
Definition sequence.h:12
constexpr auto min
Definition min.h:47
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
constexpr auto operator==(MoveIterator< Iter > const &a, MoveIterator< U > const &b) -> bool
Definition move_iterator.h:85
constexpr auto size
Definition size.h:54
constexpr auto iterator_swap
Definition iterator_swap.h:49
ZipView(Cons &&...) -> ZipView< meta::AsView< Cons >... >
constexpr auto end
Definition end.h:47
constexpr auto begin
Definition begin.h:44
constexpr auto unpack
Definition unpack.h:24
Definition merge_interfaces.h:6
decltype(container::end(util::declval< T & >())) ContainerSentinel
Definition container_sentinel.h:8
detail::CommonTypeHelper< Types... >::Type CommonType
Definition common.h:62
MakeIntegerSequence< usize, count > MakeIndexSequence
Definition algorithm.h:285
detail::MakeUnsignedHelper< RemoveCV< T > >::Type MakeUnsigned
Definition language.h:362
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
constexpr auto get(T &&value) -> decltype(auto)
Definition get.h:8
constexpr auto tuple_transform(F &&function, Tup &&tuple)
Definition tuple_transform.h:22
constexpr auto apply(F &&f, Tup &&tuple) -> decltype(detail::apply_impl(meta::MakeIndexSequence< meta::TupleSize< Tup > > {}, util::forward< F >(f), util::forward< Tup >(tuple)))
Definition apply.h:22
constexpr void tuple_for_each(F &&function, Tup &&tuple)
Definition tuple_for_each.h:22
Definition enable_borrowed_container.h:9
Definition iterator_base.h:14
Definition core.h:8