Iros
 
Loading...
Searching...
No Matches
join_view.h
Go to the documentation of this file.
1#pragma once
2
8#include "di/meta/util.h"
10#include "di/util/store_if.h"
11
12namespace di::container {
13template<concepts::InputContainer View>
14requires(concepts::View<View> && concepts::InputContainer<meta::ContainerReference<View>>)
16private:
17 template<bool is_const>
19
20 template<bool is_const>
22
23 template<bool is_const>
25
26 template<bool is_const>
29
30 template<typename Con>
31 constexpr static bool IsCommon =
35
36 template<typename Con>
37 constexpr static bool IsBidirectional =
40
41 template<typename Con>
42 constexpr static bool IsForward =
45
46 template<bool is_const>
47 class Iterator
48 : public IteratorBase<
49 Iterator<is_const>,
50 meta::Conditional<IsBidirectional<Base<is_const>>, BidirectionalIteratorTag,
51 meta::Conditional<IsForward<Base<is_const>>, ForwardIteratorTag, InputIteratorTag>>,
52 Value<is_const>, SSizeType<is_const>> {
53 private:
57
58 constexpr static bool ref_is_glvalue = concepts::Reference<meta::IteratorReference<Outer>>;
59
60 public:
61 Iterator()
63 = default;
64
65 Iterator(Iterator const&) = delete;
66 auto operator=(Iterator const&) -> Iterator& = delete;
67
68 Iterator(Iterator const&)
69 requires(IsForward<Base<is_const>>)
70 = default;
71 auto operator=(Iterator const&) -> Iterator& requires(IsForward<Base<is_const>>) = default;
72
73 Iterator(Iterator&&) = default;
74 auto operator=(Iterator&&) -> Iterator& = default;
75
76 constexpr Iterator(Parent& parent, Outer outer)
77 : m_parent(util::addressof(parent)), m_outer(util::move(outer)) {
78 this->satisfy();
79 }
80
81 constexpr Iterator(Iterator<!is_const> other)
82 requires(is_const && concepts::ConvertibleTo<meta::ContainerIterator<View>, Outer> &&
84 : m_parent(other.m_parent), m_outer(util::move(other.m_outer)), m_inner(util::move(other.m_outer)) {}
85
86 constexpr auto operator*() const -> decltype(auto) { return *m_inner; }
87
88 constexpr auto operator->() const -> Inner
89 requires(requires(Inner const i) { i.operator->(); })
90 {
91 return m_inner;
92 }
93
94 constexpr auto outer() const -> Outer const& { return m_outer; }
95
96 constexpr void advance_one() {
97 auto&& inner_container = [&]() -> auto&& {
98 if constexpr (ref_is_glvalue) {
99 return *m_outer;
100 } else {
101 return *m_parent->m_inner.value;
102 }
103 }();
104
105 if (++m_inner == container::end(inner_container)) {
106 ++m_outer;
107 satisfy();
108 }
109 }
110
111 constexpr void back_one()
112 requires(IsBidirectional<Base<is_const>>)
113 {
114 if (m_outer == container::end(m_parent->m_base)) {
115 m_inner = container::end(*--m_outer);
116 }
117 while (m_inner == container::begin(*m_outer)) {
118 m_inner = container::end(*--m_outer);
119 }
120 --m_inner;
121 }
122
123 private:
124 template<bool other_is_const>
125 friend class Iterator;
126
127 constexpr void satisfy() {
128 auto update_inner = [&](meta::ContainerIterator<Base<is_const>> const& x) -> auto&& {
129 if constexpr (ref_is_glvalue) {
130 return *x;
131 } else {
132 return m_parent->m_inner.value.emplace_deref(x);
133 }
134 };
135
136 for (; m_outer != container::end(m_parent->m_base); ++m_outer) {
137 auto&& inner = update_inner(m_outer);
138 m_inner = container::begin(inner);
139 if (m_inner != container::end(inner)) {
140 return;
141 }
142 }
143
144 if constexpr (ref_is_glvalue) {
145 m_inner = Inner();
146 }
147 }
148
149 constexpr friend auto operator==(Iterator const& a, Iterator const& b) -> bool
151 {
152 return a.m_outer == b.m_outer && a.m_inner == b.m_inner;
153 }
154
155 constexpr friend auto tag_invoke(types::Tag<iterator_move>, Iterator const& a) -> decltype(auto) {
156 return container::iterator_move(a.m_inner);
157 }
158
159 constexpr friend void tag_invoke(types::Tag<iterator_swap>, Iterator const& a, Iterator const& b)
161 {
162 return container::iterator_swap(a.m_inner, b.m_inner);
163 }
164
165 Parent* m_parent { nullptr };
166 Outer m_outer {};
167 Inner m_inner {};
168 };
169
170 template<bool is_const>
171 class Sentinel {
172 private:
174
175 public:
176 Sentinel() = default;
177
178 constexpr explicit Sentinel(Parent& parent) : m_base(container::end(parent.m_base)) {}
179
180 constexpr Sentinel(Sentinel<!is_const> other)
181 requires(is_const && concepts::ConvertibleTo<Sent<false>, Sent<true>>)
182 : m_base(other.base()) {}
183
184 constexpr auto base() const { return m_base; }
185
186 private:
187 constexpr friend auto operator==(Iterator<is_const> const& a, Sentinel const& b) -> bool {
188 return a.outer() == b.m_base;
189 }
190
191 Sent<is_const> m_base;
192 };
193
194public:
197 = default;
198
199 constexpr explicit JoinView(View base) : m_base(util::move(base)) {}
200
201 constexpr auto base() const& -> View
202 requires(concepts::CopyConstructible<View>)
203 {
204 return m_base;
205 }
206 constexpr auto base() && -> View { return util::move(m_base); }
207
208 constexpr auto begin()
210 {
211 return Iterator<false>(*this, container::begin(m_base));
212 }
213
214 constexpr auto begin() const
215 requires(concepts::InputContainer<View const> && concepts::Reference<meta::ContainerReference<View const>>)
216 {
217 return Iterator<true>(*this, container::begin(m_base));
218 }
219
220 constexpr auto end() {
221 if constexpr (IsCommon<View>) {
222 return Iterator<concepts::SimpleView<View>>(*this, container::end(m_base));
223 } else {
224 return Sentinel<concepts::SimpleView<View>>(*this);
225 }
226 }
227
228 constexpr auto end() const
229 requires(concepts::InputContainer<View const> && concepts::Reference<meta::ContainerReference<View const>>)
230 {
231 if constexpr (IsCommon<View const>) {
232 return Iterator<true>(*this, container::end(m_base));
233 } else {
234 return Sentinel<true>(*this);
235 }
236 }
237
238private:
239 template<bool is_const>
240 friend class Iterator;
241
242 View m_base;
245 m_inner;
246};
247
248template<typename Con>
250}
Definition join_view.h:15
constexpr auto end()
Definition join_view.h:220
constexpr auto base() const &-> View requires(concepts::CopyConstructible< View >)
Definition join_view.h:201
constexpr JoinView(View base)
Definition join_view.h:199
constexpr auto base() &&-> View
Definition join_view.h:206
constexpr auto end() const
Definition join_view.h:228
constexpr auto begin() const
Definition join_view.h:214
constexpr auto begin()
Definition join_view.h:208
Definition view_interface.h:26
Definition view.h:35
Definition bidirectional_container.h:8
Definition common_container.h:10
Definition operations.h:99
Definition operations.h:27
Definition compare.h:82
Definition forward_container.h:8
Definition indirectly_swappable.h:7
Definition language.h:50
Definition simple_view.h:11
Definition any_storable.h:9
Definition sequence.h:12
constexpr auto iterator_move
Definition iterator_move.h:56
constexpr auto move
Definition move.h:38
JoinView(Con &&) -> JoinView< meta::AsView< Con > >
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
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
IteratorSSizeType< ContainerIterator< T > > ContainerSSizeType
Definition container_ssize_type.h:8
decltype(container::end(util::declval< T & >())) ContainerSentinel
Definition container_sentinel.h:8
detail::CommonTypeHelper< Types... >::Type CommonType
Definition common.h:62
Conditional< is_const, T const, T > MaybeConst
Definition util.h:9
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
Definition iterator_base.h:14
Definition store_if.h:7