Iros
 
Loading...
Searching...
No Matches
join_with_view.h
Go to the documentation of this file.
1#pragma once
2
10#include "di/meta/util.h"
12#include "di/util/store_if.h"
14
15namespace di::container {
16namespace detail {
17 template<typename Con, typename Pattern>
22
23 template<typename Con>
25}
26
27template<concepts::InputContainer View, concepts::ForwardContainer Pattern>
30class JoinWithView : public ViewInterface<JoinWithView<View, Pattern>> {
31private:
32 using InnerContainer = meta::ContainerReference<View>;
33
34 template<bool other_is_const>
35 class Sentinel;
36
37 template<bool is_const>
38 class Iterator
39 : public IteratorBase<
40 Iterator<is_const>,
41 meta::Conditional<
42 concepts::Reference<meta::ContainerReference<meta::MaybeConst<is_const, View>>> &&
43 concepts::BidirectionalContainer<meta::MaybeConst<is_const, View>> &&
44 detail::BidirectionalCommon<meta::ContainerReference<meta::MaybeConst<is_const, View>>> &&
45 detail::BidirectionalCommon<meta::MaybeConst<is_const, Pattern>>,
46 BidirectionalIteratorTag,
47 meta::Conditional<
48 concepts::Reference<meta::ContainerReference<meta::MaybeConst<is_const, View>>> &&
49 concepts::ForwardIterator<meta::ContainerIterator<meta::MaybeConst<is_const, View>>> &&
50 concepts::ForwardIterator<
51 meta::ContainerIterator<meta::ContainerReference<meta::MaybeConst<is_const, View>>>>,
52 ForwardIteratorTag, InputIteratorTag>>,
53 meta::CommonType<meta::ContainerValue<meta::ContainerReference<meta::MaybeConst<is_const, View>>>,
54 meta::ContainerValue<meta::MaybeConst<is_const, Pattern>>>,
55 meta::CommonType<meta::ContainerSSizeType<meta::MaybeConst<is_const, View>>,
56 meta::ContainerSSizeType<meta::ContainerReference<meta::MaybeConst<is_const, View>>>,
57 meta::ContainerSSizeType<meta::MaybeConst<is_const, Pattern>>>> {
58 private:
61 using InnerBase = meta::ContainerReference<Base>;
62 using PatternBase = meta::MaybeConst<is_const, Pattern>;
63
64 using OuterIter = meta::ContainerIterator<Base>;
65 using InnerIter = meta::ContainerIterator<InnerBase>;
66 using PatternIter = meta::ContainerIterator<PatternBase>;
67
68 constexpr static bool ref_is_glvalue = concepts::Reference<InnerBase>;
69
70 constexpr Iterator(Parent& parent, OuterIter outer)
71 : m_parent(util::addressof(parent)), m_outer(util::move(outer)) {
72 if (m_outer != container::end(parent.m_base)) {
73 auto&& inner = this->update_inner(m_outer);
74 m_inner.template emplace<1>(container::begin(inner));
75 satisfy();
76 }
77 }
78
79 public:
80 Iterator()
82 = default;
83
84 Iterator(Iterator const&) = delete;
85 auto operator=(Iterator const&) -> Iterator& = delete;
86
87 Iterator(Iterator const&)
89 = default;
90 auto operator=(Iterator const&) -> Iterator& requires(
92
93 Iterator(Iterator&&) = default;
94 auto operator=(Iterator&&) -> Iterator& = default;
95
96 constexpr Iterator(Iterator<!is_const> other)
97 requires(is_const && concepts::ConvertibleTo<meta::ContainerIterator<View>, OuterIter> &&
100 : m_parent(other.m_parent), m_outer(util::move(other.m_outer)), m_inner(util::move(other.m_inner)) {}
101
102 constexpr auto operator*() const -> decltype(auto) {
103 using Reference =
105 return visit(
106 [](auto& it) -> Reference {
107 return *it;
108 },
109 m_inner);
110 }
111
112 constexpr void advance_one() {
113 visit(
114 [](auto& it) {
115 ++it;
116 },
117 m_inner);
118 satisfy();
119 }
120
121 constexpr void back_one()
124 {
125 if (m_outer == container::end(m_parent->m_base)) {
126 auto&& inner = *--m_outer;
127 m_inner.template emplace<1>(container::end(inner));
128 }
129
130 for (;;) {
131 if (m_inner.index() == 0) {
132 auto& it = util::get<0>(m_inner);
133 if (it == container::begin(m_pattern->m_pattern)) {
134 auto&& inner = *--m_outer;
135 m_inner.template emplace<1>(container::end(inner));
136 } else {
137 break;
138 }
139 } else {
140 auto& it = util::get<1>(m_inner);
141 auto&& inner = *m_outer;
142 if (it == container::begin(inner)) {
143 m_inner.template emplace<0>(container::end(m_parent->m_pattern));
144 } else {
145 break;
146 }
147 }
148 }
149
150 visit(
151 [](auto& it) {
152 --it;
153 },
154 m_inner);
155 }
156
157 constexpr auto outer() const -> OuterIter const& { return m_outer; }
158
159 private:
160 template<bool other_is_const>
161 friend class Iterator;
162
163 template<bool other_is_const>
164 friend class Sentinel;
165
166 friend class JoinWithView;
167
168 constexpr auto update_inner(OuterIter const& x) -> auto&& {
169 if constexpr (ref_is_glvalue) {
170 return *x;
171 } else {
172 return m_parent->m_inner.value.emplace_deref(x);
173 }
174 }
175
176 constexpr auto get_inner(OuterIter const& x) -> auto&& {
177 if constexpr (ref_is_glvalue) {
178 return *x;
179 } else {
180 return *m_parent->m_inner.value;
181 }
182 }
183
184 constexpr void satisfy() {
185 for (;;) {
186 if (m_inner.index() == 0) {
187 if (util::get<0>(m_inner) != container::end(m_parent->m_pattern)) {
188 break;
189 }
190
191 m_inner.template emplace<1>(container::begin(this->update_inner(m_outer)));
192 } else {
193 auto&& inner = this->get_inner(m_outer);
194 if (util::get<1>(m_inner) != container::end(inner)) {
195 break;
196 }
197
198 if (++m_outer == container::end(m_parent->m_base)) {
199 if constexpr (ref_is_glvalue) {
200 m_inner.template emplace<0>();
201 }
202 break;
203 }
204
205 m_inner.template emplace<0>(container::begin(m_parent->m_pattern));
206 }
207 }
208 }
209
210 constexpr friend auto operator==(Iterator const& x, Iterator const& y) -> bool
212 {
213 return x.m_outer == y.m_outer && x.m_inner == y.m_inner;
214 }
215
216 constexpr friend auto tag_invoke(types::Tag<iterator_move>, Iterator const& x) -> decltype(auto) {
218 return visit<RValue>(container::iterator_move, x.m_inner);
219 }
220
221 constexpr friend void tag_invoke(types::Tag<iterator_swap>, Iterator const& x, Iterator const& y)
223 {
224 visit(container::iterator_swap, x.m_inner, y.m_inner);
225 }
226
227 Parent* m_parent { nullptr };
228 OuterIter m_outer {};
230 };
231
232 template<bool is_const>
233 class Sentinel {
234 private:
237
238 constexpr explicit Sentinel(Parent& parent) : m_base(container::end(parent.m_base)) {}
239
240 public:
241 Sentinel() = default;
242
243 constexpr Sentinel(Sentinel<!is_const> other)
245 : m_base(util::move(other.m_base)) {}
246
247 private:
248 template<bool other_is_const>
249 friend class Iterator;
250
251 template<bool other_is_const>
252 friend class Sentinel;
253
254 friend class JoinWithView;
255
256 template<bool other_is_const>
259 constexpr friend auto operator==(Iterator<other_is_const> const& x, Sentinel const& y) -> bool {
260 return x.outer() == y.m_base;
261 }
262
264 };
265
266public:
269 = default;
270
271 constexpr JoinWithView(View base, Pattern pattern) : m_base(util::move(base)), m_pattern(util::move(pattern)) {}
272
273 template<concepts::InputContainer Con>
277 : m_base(view::all(util::forward<Con>(container))), m_pattern(SingleView { util::move(value) }) {}
278
279 constexpr auto base() const& -> View
280 requires(concepts::CopyConstructible<View>)
281 {
282 return m_base;
283 }
284 constexpr auto base() && -> View { return util::move(m_base); }
285
286 constexpr auto begin() {
287 constexpr bool is_const =
289 return Iterator<is_const>(*this, container::begin(m_base));
290 }
291
292 constexpr auto begin() const
293 requires(concepts::InputContainer<View const> && concepts::ForwardContainer<Pattern const> &&
294 concepts::Reference<meta::ContainerReference<View const>>)
295 {
296 return Iterator<true>(*this, container::begin(m_base));
297 }
298
309
310 constexpr auto end() const
311 requires(concepts::InputContainer<View const> && concepts::ForwardContainer<Pattern const> &&
312 concepts::Reference<meta::ContainerReference<View const>>)
313 {
314 using ConstInnerContainer = meta::ContainerReference<View const>;
317 return Iterator<true>(*this, container::end(m_base));
318 } else {
319 return Sentinel<true>(*this);
320 }
321 }
322
323private:
324 template<bool is_const>
325 friend class Iterator;
326
327 View m_base;
328 Pattern m_pattern;
330 m_inner;
331};
332
333template<typename Con, typename Pattern>
335
336template<concepts::InputContainer Con>
339}
Definition join_with_view.h:30
constexpr JoinWithView(View base, Pattern pattern)
Definition join_with_view.h:271
constexpr auto begin() const
Definition join_with_view.h:292
constexpr auto base() const &-> View requires(concepts::CopyConstructible< View >)
Definition join_with_view.h:279
constexpr auto base() &&-> View
Definition join_with_view.h:284
constexpr auto end() const
Definition join_with_view.h:310
constexpr auto end()
Definition join_with_view.h:299
constexpr JoinWithView(Con &&container, meta::ContainerValue< InnerContainer > value)
Definition join_with_view.h:276
constexpr auto begin()
Definition join_with_view.h:286
Definition single_view.h:15
Definition view_interface.h:26
Definition view.h:35
Definition variant_forward_declaration.h:6
Definition bidirectional_container.h:8
Definition common_container.h:10
Definition common.h:203
Definition common.h:208
Definition operations.h:11
Definition operations.h:99
Definition operations.h:27
Definition compare.h:82
Definition forward_container.h:8
Definition forward_iterator.h:10
Definition indirectly_swappable.h:7
Definition input_container.h:8
Definition language.h:50
Definition sentinel_for.h:9
Definition simple_view.h:11
Definition view.h:10
Definition join_with_view.h:24
Definition any_storable.h:9
Definition sequence.h:13
Definition adjacent.h:8
Definition sequence.h:12
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 iterator_swap
Definition iterator_swap.h:49
JoinWithView(Con &&, Pattern &&) -> JoinWithView< meta::AsView< Con >, meta::AsView< Pattern > >
constexpr auto end
Definition end.h:47
auto tag_invoke(types::Tag< util::deduce_create >, InPlaceTemplate< NodeHashMap >, Con &&) -> NodeHashMap< meta::TupleElement< T, 0 >, meta::TupleElement< T, 1 > >
constexpr auto begin
Definition begin.h:44
Definition merge_interfaces.h:6
IteratorRValue< ContainerIterator< T > > ContainerRValue
Definition container_rvalue.h:8
decltype(container::end(util::declval< T & >())) ContainerSentinel
Definition container_sentinel.h:8
decltype(container::iterator_move(util::declval< T & >())) IteratorRValue
Definition iterator_rvalue.h:9
detail::CommonReferenceHelper< Types... >::Type CommonReference
Definition common.h:198
IteratorReference< ContainerIterator< T > > ContainerReference
Definition container_reference.h:8
Conditional< is_const, T const, T > MaybeConst
Definition util.h:9
decltype(container::view::all(util::declval< Con >())) AsView
Definition as_view.h:9
decltype(*util::declval< T const & >()) IteratorReference
Definition iterator_reference.h:7
IteratorValue< ContainerIterator< T > > ContainerValue
Definition container_value.h:8
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 visit(Vis &&visitor, Vars &&... variants) -> R
Definition visit.h:39
Definition iterator_base.h:14
Definition store_if.h:7