di 0.1.0
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>
18 concept CompatibleJoinableContainers =
19 concepts::CommonWith<meta::ContainerValue<Con>, meta::ContainerValue<Pattern>> &&
20 concepts::CommonReferenceWith<meta::ContainerReference<Con>, meta::ContainerReference<Pattern>> &&
21 concepts::CommonReferenceWith<meta::ContainerRValue<Con>, meta::ContainerRValue<Pattern>>;
22
23 template<typename Con>
24 concept BidirectionalCommon = concepts::BidirectionalContainer<Con> && concepts::CommonContainer<Con>;
25}
26
27template<concepts::InputContainer View, concepts::ForwardContainer Pattern>
28requires(concepts::View<View> && concepts::InputContainer<meta::ContainerReference<View>> && concepts::View<Pattern> &&
29 detail::CompatibleJoinableContainers<meta::ContainerReference<View>, 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&
92 = default;
93
94 Iterator(Iterator&&) = default;
95 auto operator=(Iterator&&) -> Iterator& = default;
96
97 constexpr Iterator(Iterator<!is_const> other)
98 requires(is_const && concepts::ConvertibleTo<meta::ContainerIterator<View>, OuterIter> &&
101 : m_parent(other.m_parent), m_outer(util::move(other.m_outer)), m_inner(util::move(other.m_inner)) {}
102
103 constexpr auto operator*() const -> decltype(auto) {
104 using Reference =
106 return visit(
107 [](auto& it) -> Reference {
108 return *it;
109 },
110 m_inner);
111 }
112
113 constexpr void advance_one() {
114 visit(
115 [](auto& it) {
116 ++it;
117 },
118 m_inner);
119 satisfy();
120 }
121
122 constexpr void back_one()
123 requires(ref_is_glvalue && concepts::BidirectionalContainer<Base> && detail::BidirectionalCommon<InnerBase> &&
124 detail::BidirectionalCommon<PatternBase>)
125 {
126 if (m_outer == container::end(m_parent->m_base)) {
127 auto&& inner = *--m_outer;
128 m_inner.template emplace<1>(container::end(inner));
129 }
130
131 for (;;) {
132 if (m_inner.index() == 0) {
133 auto& it = util::get<0>(m_inner);
134 if (it == container::begin(m_pattern->m_pattern)) {
135 auto&& inner = *--m_outer;
136 m_inner.template emplace<1>(container::end(inner));
137 } else {
138 break;
139 }
140 } else {
141 auto& it = util::get<1>(m_inner);
142 auto&& inner = *m_outer;
143 if (it == container::begin(inner)) {
144 m_inner.template emplace<0>(container::end(m_parent->m_pattern));
145 } else {
146 break;
147 }
148 }
149 }
150
151 visit(
152 [](auto& it) {
153 --it;
154 },
155 m_inner);
156 }
157
158 constexpr auto outer() const -> OuterIter const& { return m_outer; }
159
160 private:
161 template<bool other_is_const>
162 friend class Iterator;
163
164 template<bool other_is_const>
165 friend class Sentinel;
166
167 friend class JoinWithView;
168
169 constexpr auto update_inner(OuterIter const& x) -> auto&& {
170 if constexpr (ref_is_glvalue) {
171 return *x;
172 } else {
173 return m_parent->m_inner.value.emplace_deref(x);
174 }
175 }
176
177 constexpr auto get_inner(OuterIter const& x) -> auto&& {
178 if constexpr (ref_is_glvalue) {
179 return *x;
180 } else {
181 return *m_parent->m_inner.value;
182 }
183 }
184
185 constexpr void satisfy() {
186 for (;;) {
187 if (m_inner.index() == 0) {
188 if (util::get<0>(m_inner) != container::end(m_parent->m_pattern)) {
189 break;
190 }
191
192 m_inner.template emplace<1>(container::begin(this->update_inner(m_outer)));
193 } else {
194 auto&& inner = this->get_inner(m_outer);
195 if (util::get<1>(m_inner) != container::end(inner)) {
196 break;
197 }
198
199 if (++m_outer == container::end(m_parent->m_base)) {
200 if constexpr (ref_is_glvalue) {
201 m_inner.template emplace<0>();
202 }
203 break;
204 }
205
206 m_inner.template emplace<0>(container::begin(m_parent->m_pattern));
207 }
208 }
209 }
210
211 constexpr friend auto operator==(Iterator const& x, Iterator const& y) -> bool
213 {
214 return x.m_outer == y.m_outer && x.m_inner == y.m_inner;
215 }
216
217 constexpr friend auto tag_invoke(types::Tag<iterator_move>, Iterator const& x) -> decltype(auto) {
219 return visit<RValue>(container::iterator_move, x.m_inner);
220 }
221
222 constexpr friend void tag_invoke(types::Tag<iterator_swap>, Iterator const& x, Iterator const& y)
224 {
225 visit(container::iterator_swap, x.m_inner, y.m_inner);
226 }
227
228 Parent* m_parent { nullptr };
229 OuterIter m_outer {};
231 };
232
233 template<bool is_const>
234 class Sentinel {
235 private:
238
239 constexpr explicit Sentinel(Parent& parent) : m_base(container::end(parent.m_base)) {}
240
241 public:
242 Sentinel() = default;
243
244 constexpr Sentinel(Sentinel<!is_const> other)
246 : m_base(util::move(other.m_base)) {}
247
248 private:
249 template<bool other_is_const>
250 friend class Iterator;
251
252 template<bool other_is_const>
253 friend class Sentinel;
254
255 friend class JoinWithView;
256
257 template<bool other_is_const>
260 constexpr friend auto operator==(Iterator<other_is_const> const& x, Sentinel const& y) -> bool {
261 return x.outer() == y.m_base;
262 }
263
265 };
266
267public:
270 = default;
271
272 constexpr JoinWithView(View base, Pattern pattern) : m_base(util::move(base)), m_pattern(util::move(pattern)) {}
273
274 template<concepts::InputContainer Con>
278 : m_base(view::all(util::forward<Con>(container))), m_pattern(SingleView { util::move(value) }) {}
279
280 constexpr auto base() const& -> View
281 requires(concepts::CopyConstructible<View>)
282 {
283 return m_base;
284 }
285 constexpr auto base() && -> View { return util::move(m_base); }
286
287 constexpr auto begin() {
288 constexpr bool is_const =
290 return Iterator<is_const>(*this, container::begin(m_base));
291 }
292
293 constexpr auto begin() const
294 requires(concepts::InputContainer<View const> && concepts::ForwardContainer<Pattern const> &&
295 concepts::Reference<meta::ContainerReference<View const>>)
296 {
297 return Iterator<true>(*this, container::begin(m_base));
298 }
299
310
311 constexpr auto end() const
312 requires(concepts::InputContainer<View const> && concepts::ForwardContainer<Pattern const> &&
313 concepts::Reference<meta::ContainerReference<View const>>)
314 {
315 using ConstInnerContainer = meta::ContainerReference<View const>;
318 return Iterator<true>(*this, container::end(m_base));
319 } else {
320 return Sentinel<true>(*this);
321 }
322 }
323
324private:
325 template<bool is_const>
326 friend class Iterator;
327
328 View m_base;
329 Pattern m_pattern;
331 m_inner;
332};
333
334template<typename Con, typename Pattern>
336
337template<concepts::InputContainer Con>
340}
Definition join_with_view.h:30
constexpr JoinWithView(View base, Pattern pattern)
Definition join_with_view.h:272
constexpr auto begin() const
Definition join_with_view.h:293
constexpr auto base() const &-> View requires(concepts::CopyConstructible< View >)
Definition join_with_view.h:280
constexpr auto base() &&-> View
Definition join_with_view.h:285
constexpr auto end() const
Definition join_with_view.h:311
constexpr auto end()
Definition join_with_view.h:300
constexpr JoinWithView(Con &&container, meta::ContainerValue< InnerContainer > value)
Definition join_with_view.h:277
constexpr auto begin()
Definition join_with_view.h:287
Definition single_view.h:15
Definition view_interface.h:26
Definition view.h:35
Definition variant.h:30
Definition bidirectional_container.h:8
Definition common_container.h:10
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 language.h:50
Definition sentinel_for.h:9
Definition simple_view.h:11
Definition any_storable.h:9
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:55
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:52
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