Iros
 
Loading...
Searching...
No Matches
adjacent_view.h
Go to the documentation of this file.
1#pragma once
2
14
15namespace di::container {
16template<concepts::ForwardContainer View, size_t N>
17requires(concepts::View<View> && N > 0)
19 : public ViewInterface<AdjacentView<View, N>>
20 , public meta::EnableBorrowedContainer<AdjacentView<View, N>, concepts::BorrowedContainer<View>> {
21private:
22 template<bool is_const>
24
25 template<bool is_const>
27
28 template<bool is_const>
30
31 template<bool is_const>
33
34 struct AsSentinel {};
35
36 template<bool is_const>
37 class Sentinel;
38
39 template<bool is_const>
40 class Iterator
41 : public IteratorBase<Iterator<is_const>,
42 meta::Conditional<concepts::RandomAccessIterator<Iter<is_const>>, RandomAccessIteratorTag,
43 meta::Conditional<concepts::BidirectionalIterator<Iter<is_const>>,
44 BidirectionalIteratorTag, ForwardIteratorTag>>,
45 meta::AsTuple<meta::Repeat<Value<is_const>, N>>, SSizeType<is_const>> {
46 public:
47 Iterator() = default;
48
49 constexpr explicit Iterator(Iter<is_const> first, Sent<is_const> last) {
50 m_iterators[0] = util::move(first);
51 for (auto i : view::range(1ZU, N)) {
52 m_iterators[i] = container::next(m_iterators[i - 1], 1, last);
53 }
54 }
55
56 constexpr explicit Iterator(AsSentinel, Iter<is_const> first, Iter<is_const> last) {
58 m_iterators[N - 1] = util::move(last);
59 for (auto i : view::range(N - 1) | view::reverse) {
60 m_iterators[i] = container::prev(m_iterators[i + 1], 1, first);
61 }
62 } else {
63 for (auto i : view::range(N)) {
64 m_iterators[i] = last;
65 }
66 }
67 }
68
69 constexpr Iterator(Iterator<!is_const> other)
70 requires(is_const && concepts::ConvertibleTo<Iter<false>, Iter<true>>)
71 {
72 for (auto& [left, right] : view::zip(this->m_iterators, other.m_iterators)) {
73 left = util::move(right);
74 }
75 }
76
77 constexpr auto operator*() const {
78 return tuple_transform(
79 [](auto& iterator) -> decltype(*iterator) {
80 return *iterator;
81 },
82 m_iterators);
83 }
84
85 constexpr void advance_one() {
87 [](auto& iterator) {
88 ++iterator;
89 },
90 m_iterators);
91 }
92
93 constexpr void back_one()
95 {
97 [](auto& iterator) {
98 --iterator;
99 },
100 m_iterators);
101 }
102
103 constexpr void advance_n(SSizeType<is_const> n)
105 {
107 [&](auto& iterator) {
108 iterator += n;
109 },
110 m_iterators);
111 }
112
113 constexpr auto iterators() const -> Array<Iter<is_const>, N> const& { return m_iterators; }
114
115 private:
116 constexpr friend auto operator==(Iterator const& a, Iterator const& b) -> bool
118 {
119 return a.m_iterators.back() == b.m_iterators.back();
120 }
121
122 constexpr friend auto operator<=>(Iterator const& a, Iterator const& b)
124 {
125 return a.m_iterators.back() <=> b.m_iterators.back();
126 }
127
128 constexpr friend auto operator-(Iterator const& a, Iterator const& b) -> SSizeType<is_const>
129 requires(concepts::SizedSentinelFor<Iter<is_const>, Iter<is_const>>)
130 {
131 return a.m_iterators.back() - b.m_iterators.back();
132 }
133
134 template<bool other_is_const>
135 friend class Sentinel;
136
137 constexpr friend auto tag_invoke(types::Tag<iterator_move>, Iterator const& self) {
138 return tuple_transform(iterator_move, self.m_iterators);
139 }
140
141 constexpr friend void tag_invoke(types::Tag<iterator_swap>, Iterator const& a, Iterator const& b)
143 {
144 return function::unpack<meta::MakeIndexSequence<N>>([&]<size_t... indices>(meta::ListV<indices...>) {
145 (void) (iterator_swap(util::get<indices>(a.m_iterators), util::get<indices>(b.m_iterators)), ...);
146 });
147 }
148
149 Array<Iter<is_const>, N> m_iterators;
150 };
151
152 template<bool is_const>
153 class Sentinel : public SentinelBase<Sentinel<is_const>> {
154 public:
155 Sentinel() = default;
156
157 constexpr explicit Sentinel(Sent<is_const> sentinel) : m_sentinel(sentinel) {}
158
159 constexpr Sentinel(Sentinel<!is_const> other)
160 requires(is_const && concepts::ConvertibleTo<Sent<false>, Sent<true>>)
161 : m_sentinel(other.base()) {}
162
163 constexpr auto base() const { return m_sentinel; }
164
165 template<bool other_is_const>
166 requires(concepts::SizedSentinelFor<Sent<is_const>, Iter<other_is_const>>)
167 constexpr auto difference(Iterator<other_is_const> const& a) const -> SSizeType<is_const> {
168 return base() - a.m_iterators.back();
169 }
170
171 private:
172 template<bool other_is_const>
173 requires(concepts::SentinelFor<Sent<is_const>, Iter<other_is_const>>)
174 constexpr friend auto operator==(Iterator<other_is_const> const& a, Sentinel const& b) -> bool {
175 return a.m_iterators.back() == b.base();
176 }
177
178 Sent<is_const> m_sentinel;
179 };
180
181public:
184 = default;
185
186 constexpr explicit AdjacentView(View base) : m_base(util::move(base)) {}
187
188 constexpr auto base() const& -> View
189 requires(concepts::CopyConstructible<View>)
190 {
191 return m_base;
192 }
193 constexpr auto base() && -> View { return util::move(m_base); }
194
195 constexpr auto begin()
197 {
198 return Iterator<false>(container::begin(m_base), container::end(m_base));
199 }
200
201 constexpr auto begin() const
202 requires(concepts::Container<View const>)
203 {
204 return Iterator<true>(container::begin(m_base), container::end(m_base));
205 }
206
207 constexpr auto end()
209 {
210 if constexpr (!concepts::CommonContainer<View>) {
211 return Sentinel<false>(container::end(m_base));
212 } else {
213 return Iterator<false>(AsSentinel {}, container::begin(m_base), container::end(m_base));
214 }
215 }
216
217 constexpr auto end() const
218 requires(concepts::Container<View const>)
219 {
221 return Sentinel<true>(container::end(m_base));
222 } else {
223 return Iterator<true>(AsSentinel {}, container::begin(m_base), container::end(m_base));
224 }
225 }
226
227 constexpr auto size()
229 {
230 using SizeType = decltype(container::size(m_base));
231 using CommonType = meta::CommonType<SizeType, size_t>;
232 auto size = static_cast<CommonType>(container::size(m_base));
233 size -= container::min(size, static_cast<CommonType>(N - 1));
234 return static_cast<SizeType>(size);
235 }
236
237 constexpr auto size() const
238 requires(concepts::SizedContainer<View const>)
239 {
240 using SizeType = decltype(container::size(m_base));
241 using CommonType = meta::CommonType<SizeType, size_t>;
242 auto size = static_cast<CommonType>(container::size(m_base));
243 size -= container::min(size, static_cast<CommonType>(N - 1));
244 return static_cast<SizeType>(size);
245 }
246
247private:
248 View m_base;
249};
250}
constexpr AdjacentView(View base)
Definition adjacent_view.h:186
constexpr auto size()
Definition adjacent_view.h:227
constexpr auto end()
Definition adjacent_view.h:207
constexpr auto base() &&-> View
Definition adjacent_view.h:193
constexpr auto end() const
Definition adjacent_view.h:217
constexpr auto base() const &-> View requires(concepts::CopyConstructible< View >)
Definition adjacent_view.h:188
constexpr auto size() const
Definition adjacent_view.h:237
constexpr auto begin() const
Definition adjacent_view.h:201
constexpr auto begin()
Definition adjacent_view.h:195
Definition sentinel_base.h:13
Definition view_interface.h:26
Definition view.h:35
constexpr friend auto tag_invoke(types::Tag< container::enable_borrowed_container >, types::InPlaceType< AdjacentView< View, N > >) -> bool
Definition enable_borrowed_container.h:9
Definition bidirectional_iterator.h:8
Definition common_container.h:10
Definition operations.h:99
Definition operations.h:27
Definition compare.h:82
Definition indirectly_swappable.h:7
Definition random_access_iterator.h:12
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
constexpr auto zip
Definition zip.h:36
constexpr auto reverse
Definition reverse.h:52
constexpr auto range
Definition range.h:22
Definition sequence.h:12
constexpr auto prev
Definition prev.h:28
constexpr auto min
Definition min.h:47
constexpr auto next
Definition next.h:35
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:54
constexpr auto iterator_swap
Definition iterator_swap.h:49
constexpr auto end
Definition end.h:47
constexpr auto begin
Definition begin.h:44
constexpr auto unpack
Definition unpack.h:24
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
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 tuple_transform(F &&function, Tup &&tuple)
Definition tuple_transform.h:22
constexpr void tuple_for_each(F &&function, Tup &&tuple)
Definition tuple_for_each.h:22
@ N
Definition key.h:23
Definition enable_borrowed_container.h:9
Definition iterator_base.h:14
Definition core.h:8
Definition span_fixed_size.h:37