di 0.1.0
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&
98 requires(!all_forward<is_const>)
99 = delete;
100
101 constexpr auto operator*() const {
102 return tuple_transform(
103 [](auto& iterator) -> decltype(*iterator) {
104 return *iterator;
105 },
106 m_iterators);
107 }
108
109 constexpr void advance_one() {
111 [](auto& iterator) {
112 ++iterator;
113 },
114 m_iterators);
115 }
116
117 constexpr void back_one()
118 requires(all_bidirectional<is_const>)
119 {
121 [](auto& iterator) {
122 --iterator;
123 },
124 m_iterators);
125 }
126
127 constexpr void advance_n(SSizeType<is_const> n)
128 requires(all_random_access<is_const>)
129 {
131 [&](auto& iterator) {
132 iterator += n;
133 },
134 m_iterators);
135 }
136
137 constexpr auto iterators() const -> Storage const& { return m_iterators; }
138
139 private:
140 constexpr friend auto operator==(Iterator const& a, Iterator const& b) -> bool
142 {
143 if constexpr (all_bidirectional<is_const>) {
144 return a.m_iterators == b.m_iterators;
145 } else {
146 return function::unpack<meta::MakeIndexSequence<sizeof...(Views)>>(
147 [&]<size_t... indices>(meta::ListV<indices...>) {
148 return ((util::get<indices>(a.m_iterators) <= util::get<indices>(b.m_iterators)) || ...);
149 });
150 }
151 }
152
153 constexpr friend auto operator<=>(Iterator const& a, Iterator const& b)
154 requires(all_random_access<is_const> &&
156 {
157 return a.m_iterators <=> b.m_iterators;
158 }
159
160 constexpr friend auto operator-(Iterator const& a, Iterator const& b) -> SSizeType<is_const>
163 ...)
164 {
165 return function::unpack<meta::MakeIndexSequence<sizeof...(Views)>>(
166 [&]<size_t... indices>(meta::ListV<indices...>) {
167 return container::min({ static_cast<SSizeType<is_const>>(util::get<indices>(a.m_iterators) -
168 util::get<indices>(b.m_iterators))... });
169 });
170 }
171
172 constexpr friend auto tag_invoke(types::Tag<iterator_move>, Iterator const& self) {
173 return tuple_transform(iterator_move, self.m_iterators);
174 }
175
176 constexpr friend void tag_invoke(types::Tag<iterator_swap>, Iterator const& a, Iterator const& b)
179 ...)
180 {
181 return function::unpack<meta::MakeIndexSequence<sizeof...(Views)>>(
182 [&]<size_t... indices>(meta::ListV<indices...>) {
183 (void) (iterator_swap(util::get<indices>(a.m_iterators), util::get<indices>(b.m_iterators)), ...);
184 });
185 }
186
187 Storage m_iterators;
188 };
189
190 template<bool is_const>
191 class Sentinel : public SentinelBase<Sentinel<is_const>> {
192 private:
194
195 constexpr explicit Sentinel(Storage sentinels) : m_sentinels(util::move(sentinels)) {}
196
197 friend class ZipView;
198
199 public:
200 Sentinel() = default;
201
202 constexpr Sentinel(Sentinel<!is_const> other)
205 ...))
206 : m_sentinels(util::move(other)) {}
207
208 template<bool other_is_const>
211 ...)
212 constexpr auto difference(Iterator<other_is_const> const& a) const {
213 return function::unpack<meta::MakeIndexSequence<sizeof...(Views)>>(
214 [&]<size_t... indices>(meta::ListV<indices...>) {
215 return container::min({ static_cast<SSizeType<is_const>>(util::get<indices>(this->m_sentinels) -
216 util::get<indices>(a.m_iterators))... });
217 });
218 }
219
220 private:
221 template<bool other_is_const>
224 ...)
225 constexpr friend auto operator==(Iterator<other_is_const> const& a, Sentinel const& b) -> bool {
226 return function::unpack<meta::MakeIndexSequence<sizeof...(Views)>>(
227 [&]<size_t... indices>(meta::ListV<indices...>) {
228 return ((util::get<indices>(a.m_iterators) == util::get<indices>(b.m_sentinels)) || ...);
229 });
230 }
231
232 Storage m_sentinels;
233 };
234
235public:
236 ZipView() = default;
237
240 = delete;
241
242 constexpr explicit ZipView(Views... views) : m_views(util::move(views)...) {}
243
244 constexpr auto begin()
245 requires(!all_simple)
246 {
247 return Iterator<false>(tuple_transform(container::begin, m_views));
248 }
249
250 constexpr auto begin() const
251 requires(all_const)
252 {
253 return Iterator<true>(tuple_transform(container::begin, m_views));
254 }
255
256 constexpr auto end()
257 requires(!all_simple)
258 {
259 if constexpr (!is_common<false>) {
260 return Sentinel<false>(tuple_transform(container::end, m_views));
261 } else if constexpr (all_random_access<false>) {
262 return begin() + static_cast<SSizeType<false>>(size());
263 } else {
264 return Iterator<false>(tuple_transform(container::end, m_views));
265 }
266 }
267
268 constexpr auto end() const
269 requires(all_const)
270 {
271 if constexpr (!is_common<true>) {
272 return Sentinel<true>(tuple_transform(container::end, m_views));
273 } else if constexpr (all_random_access<true>) {
274 return begin() + static_cast<SSizeType<true>>(size());
275 } else {
276 return Iterator<true>(tuple_transform(container::end, m_views));
277 }
278 }
279
280 constexpr auto size()
281 requires(all_sized<false>)
282 {
283 return apply(
284 [](auto... sizes) {
285 using CommonType = meta::MakeUnsigned<meta::CommonType<decltype(sizes)...>>;
286 return container::min({ static_cast<CommonType>(sizes)... });
287 },
289 }
290
291 constexpr auto size() const
292 requires(all_sized<true>)
293 {
294 return apply(
295 [](auto... sizes) {
296 using CommonType = meta::MakeUnsigned<meta::CommonType<decltype(sizes)...>>;
297 return container::min({ static_cast<CommonType>(sizes)... });
298 },
300 }
301
302private:
303 Tuple<Views...> m_views;
304};
305
306template<typename... Cons>
308}
Definition sentinel_base.h:13
Definition view_interface.h:26
Definition zip_view.h:24
constexpr auto end()
Definition zip_view.h:256
constexpr auto size() const
Definition zip_view.h:291
constexpr ZipView(Views... views)
Definition zip_view.h:242
constexpr auto end() const
Definition zip_view.h:268
constexpr auto begin()
Definition zip_view.h:244
constexpr auto size()
Definition zip_view.h:280
constexpr auto begin() const
Definition zip_view.h:250
constexpr friend auto tag_invoke(types::Tag< container::enable_borrowed_container >, types::InPlaceType< ZipView< Views... > >) -> bool
Definition enable_borrowed_container.h:9
Definition tuple.h:27
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:49
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:62
constexpr auto iterator_swap
Definition iterator_swap.h:49
ZipView(Cons &&...) -> ZipView< meta::AsView< Cons >... >
constexpr auto end
Definition end.h:55
constexpr auto begin
Definition begin.h:52
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:333
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