di 0.1.0
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&
72 requires(IsForward<Base<is_const>>)
73 = default;
74
75 Iterator(Iterator&&) = default;
76 auto operator=(Iterator&&) -> Iterator& = default;
77
78 constexpr Iterator(Parent& parent, Outer outer)
79 : m_parent(util::addressof(parent)), m_outer(util::move(outer)) {
80 this->satisfy();
81 }
82
83 constexpr Iterator(Iterator<!is_const> other)
84 requires(is_const && concepts::ConvertibleTo<meta::ContainerIterator<View>, Outer> &&
86 : m_parent(other.m_parent), m_outer(util::move(other.m_outer)), m_inner(util::move(other.m_outer)) {}
87
88 constexpr auto operator*() const -> decltype(auto) { return *m_inner; }
89
90 constexpr auto operator->() const -> Inner
91 requires(requires(Inner const i) { i.operator->(); })
92 {
93 return m_inner;
94 }
95
96 constexpr auto outer() const -> Outer const& { return m_outer; }
97
98 constexpr void advance_one() {
99 auto&& inner_container = [&]() -> auto&& {
100 if constexpr (ref_is_glvalue) {
101 return *m_outer;
102 } else {
103 return *m_parent->m_inner.value;
104 }
105 }();
106
107 if (++m_inner == container::end(inner_container)) {
108 ++m_outer;
109 satisfy();
110 }
111 }
112
113 constexpr void back_one()
114 requires(IsBidirectional<Base<is_const>>)
115 {
116 if (m_outer == container::end(m_parent->m_base)) {
117 m_inner = container::end(*--m_outer);
118 }
119 while (m_inner == container::begin(*m_outer)) {
120 m_inner = container::end(*--m_outer);
121 }
122 --m_inner;
123 }
124
125 private:
126 template<bool other_is_const>
127 friend class Iterator;
128
129 constexpr void satisfy() {
130 auto update_inner = [&](meta::ContainerIterator<Base<is_const>> const& x) -> auto&& {
131 if constexpr (ref_is_glvalue) {
132 return *x;
133 } else {
134 return m_parent->m_inner.value.emplace_deref(x);
135 }
136 };
137
138 for (; m_outer != container::end(m_parent->m_base); ++m_outer) {
139 auto&& inner = update_inner(m_outer);
140 m_inner = container::begin(inner);
141 if (m_inner != container::end(inner)) {
142 return;
143 }
144 }
145
146 if constexpr (ref_is_glvalue) {
147 m_inner = Inner();
148 }
149 }
150
151 constexpr friend auto operator==(Iterator const& a, Iterator const& b) -> bool
153 {
154 return a.m_outer == b.m_outer && a.m_inner == b.m_inner;
155 }
156
157 constexpr friend auto tag_invoke(types::Tag<iterator_move>, Iterator const& a) -> decltype(auto) {
158 return container::iterator_move(a.m_inner);
159 }
160
161 constexpr friend void tag_invoke(types::Tag<iterator_swap>, Iterator const& a, Iterator const& b)
163 {
164 return container::iterator_swap(a.m_inner, b.m_inner);
165 }
166
167 Parent* m_parent { nullptr };
168 Outer m_outer {};
169 Inner m_inner {};
170 };
171
172 template<bool is_const>
173 class Sentinel {
174 private:
176
177 public:
178 Sentinel() = default;
179
180 constexpr explicit Sentinel(Parent& parent) : m_base(container::end(parent.m_base)) {}
181
182 constexpr Sentinel(Sentinel<!is_const> other)
183 requires(is_const && concepts::ConvertibleTo<Sent<false>, Sent<true>>)
184 : m_base(other.base()) {}
185
186 constexpr auto base() const { return m_base; }
187
188 private:
189 constexpr friend auto operator==(Iterator<is_const> const& a, Sentinel const& b) -> bool {
190 return a.outer() == b.m_base;
191 }
192
193 Sent<is_const> m_base;
194 };
195
196public:
199 = default;
200
201 constexpr explicit JoinView(View base) : m_base(util::move(base)) {}
202
203 constexpr auto base() const& -> View
204 requires(concepts::CopyConstructible<View>)
205 {
206 return m_base;
207 }
208 constexpr auto base() && -> View { return util::move(m_base); }
209
210 constexpr auto begin()
212 {
213 return Iterator<false>(*this, container::begin(m_base));
214 }
215
216 constexpr auto begin() const
217 requires(concepts::InputContainer<View const> && concepts::Reference<meta::ContainerReference<View const>>)
218 {
219 return Iterator<true>(*this, container::begin(m_base));
220 }
221
222 constexpr auto end() {
223 if constexpr (IsCommon<View>) {
224 return Iterator<concepts::SimpleView<View>>(*this, container::end(m_base));
225 } else {
226 return Sentinel<concepts::SimpleView<View>>(*this);
227 }
228 }
229
230 constexpr auto end() const
231 requires(concepts::InputContainer<View const> && concepts::Reference<meta::ContainerReference<View const>>)
232 {
233 if constexpr (IsCommon<View const>) {
234 return Iterator<true>(*this, container::end(m_base));
235 } else {
236 return Sentinel<true>(*this);
237 }
238 }
239
240private:
241 template<bool is_const>
242 friend class Iterator;
243
244 View m_base;
247 m_inner;
248};
249
250template<typename Con>
252}
Definition join_view.h:15
constexpr auto end()
Definition join_view.h:222
constexpr auto base() const &-> View requires(concepts::CopyConstructible< View >)
Definition join_view.h:203
constexpr JoinView(View base)
Definition join_view.h:201
constexpr auto base() &&-> View
Definition join_view.h:208
constexpr auto end() const
Definition join_view.h:230
constexpr auto begin() const
Definition join_view.h:216
constexpr auto begin()
Definition join_view.h:210
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: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
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