1 | // -*- C++ -*- |
2 | //===----------------------------------------------------------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef _LIBCPP___RANGES_TRANSFORM_VIEW_H |
11 | #define _LIBCPP___RANGES_TRANSFORM_VIEW_H |
12 | |
13 | #include <__compare/three_way_comparable.h> |
14 | #include <__concepts/constructible.h> |
15 | #include <__concepts/convertible_to.h> |
16 | #include <__concepts/copyable.h> |
17 | #include <__concepts/derived_from.h> |
18 | #include <__concepts/equality_comparable.h> |
19 | #include <__concepts/invocable.h> |
20 | #include <__config> |
21 | #include <__functional/bind_back.h> |
22 | #include <__functional/invoke.h> |
23 | #include <__functional/perfect_forward.h> |
24 | #include <__iterator/concepts.h> |
25 | #include <__iterator/iterator_traits.h> |
26 | #include <__memory/addressof.h> |
27 | #include <__ranges/access.h> |
28 | #include <__ranges/all.h> |
29 | #include <__ranges/concepts.h> |
30 | #include <__ranges/empty.h> |
31 | #include <__ranges/movable_box.h> |
32 | #include <__ranges/range_adaptor.h> |
33 | #include <__ranges/size.h> |
34 | #include <__ranges/view_interface.h> |
35 | #include <__type_traits/conditional.h> |
36 | #include <__type_traits/decay.h> |
37 | #include <__type_traits/is_nothrow_constructible.h> |
38 | #include <__type_traits/is_object.h> |
39 | #include <__type_traits/is_reference.h> |
40 | #include <__type_traits/maybe_const.h> |
41 | #include <__type_traits/remove_cvref.h> |
42 | #include <__utility/forward.h> |
43 | #include <__utility/in_place.h> |
44 | #include <__utility/move.h> |
45 | |
46 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
47 | # pragma GCC system_header |
48 | #endif |
49 | |
50 | _LIBCPP_PUSH_MACROS |
51 | #include <__undef_macros> |
52 | |
53 | _LIBCPP_BEGIN_NAMESPACE_STD |
54 | |
55 | #if _LIBCPP_STD_VER >= 20 |
56 | |
57 | namespace ranges { |
58 | |
59 | template <class _Fn, class _View> |
60 | concept __regular_invocable_with_range_ref = regular_invocable<_Fn, range_reference_t<_View>>; |
61 | |
62 | template <class _View, class _Fn> |
63 | concept __transform_view_constraints = |
64 | view<_View> && is_object_v<_Fn> && regular_invocable<_Fn&, range_reference_t<_View>> && |
65 | __can_reference<invoke_result_t<_Fn&, range_reference_t<_View>>>; |
66 | |
67 | # if _LIBCPP_STD_VER >= 23 |
68 | template <input_range _View, move_constructible _Fn> |
69 | # else |
70 | template <input_range _View, copy_constructible _Fn> |
71 | # endif |
72 | requires __transform_view_constraints<_View, _Fn> |
73 | class _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS transform_view : public view_interface<transform_view<_View, _Fn>> { |
74 | template <bool> |
75 | class __iterator; |
76 | template <bool> |
77 | class __sentinel; |
78 | |
79 | _LIBCPP_NO_UNIQUE_ADDRESS __movable_box<_Fn> __func_; |
80 | _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View(); |
81 | |
82 | public: |
83 | _LIBCPP_HIDE_FROM_ABI transform_view() |
84 | requires default_initializable<_View> && default_initializable<_Fn> |
85 | = default; |
86 | |
87 | _LIBCPP_HIDE_FROM_ABI constexpr _LIBCPP_EXPLICIT_SINCE_CXX23 transform_view(_View __base, _Fn __func) |
88 | : __func_(std::in_place, std::move(__func)), __base_(std::move(__base)) {} |
89 | |
90 | _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& |
91 | requires copy_constructible<_View> |
92 | { |
93 | return __base_; |
94 | } |
95 | _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); } |
96 | |
97 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator<false> begin() { return __iterator<false>{*this, ranges::begin(__base_)}; } |
98 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator<true> begin() const |
99 | requires range<const _View> && __regular_invocable_with_range_ref<const _Fn&, const _View> |
100 | { |
101 | return __iterator<true>(*this, ranges::begin(__base_)); |
102 | } |
103 | |
104 | _LIBCPP_HIDE_FROM_ABI constexpr __sentinel<false> end() { return __sentinel<false>(ranges::end(__base_)); } |
105 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator<false> end() |
106 | requires common_range<_View> |
107 | { |
108 | return __iterator<false>(*this, ranges::end(__base_)); |
109 | } |
110 | _LIBCPP_HIDE_FROM_ABI constexpr __sentinel<true> end() const |
111 | requires range<const _View> && __regular_invocable_with_range_ref<const _Fn&, const _View> |
112 | { |
113 | return __sentinel<true>(ranges::end(__base_)); |
114 | } |
115 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator<true> end() const |
116 | requires common_range<const _View> && __regular_invocable_with_range_ref<const _Fn&, const _View> |
117 | { |
118 | return __iterator<true>(*this, ranges::end(__base_)); |
119 | } |
120 | |
121 | _LIBCPP_HIDE_FROM_ABI constexpr auto size() |
122 | requires sized_range<_View> |
123 | { |
124 | return ranges::size(__base_); |
125 | } |
126 | _LIBCPP_HIDE_FROM_ABI constexpr auto size() const |
127 | requires sized_range<const _View> |
128 | { |
129 | return ranges::size(__base_); |
130 | } |
131 | }; |
132 | |
133 | template <class _Range, class _Fn> |
134 | transform_view(_Range&&, _Fn) -> transform_view<views::all_t<_Range>, _Fn>; |
135 | |
136 | template <class _View> |
137 | struct __transform_view_iterator_concept { |
138 | using type = input_iterator_tag; |
139 | }; |
140 | |
141 | template <random_access_range _View> |
142 | struct __transform_view_iterator_concept<_View> { |
143 | using type = random_access_iterator_tag; |
144 | }; |
145 | |
146 | template <bidirectional_range _View> |
147 | struct __transform_view_iterator_concept<_View> { |
148 | using type = bidirectional_iterator_tag; |
149 | }; |
150 | |
151 | template <forward_range _View> |
152 | struct __transform_view_iterator_concept<_View> { |
153 | using type = forward_iterator_tag; |
154 | }; |
155 | |
156 | template <class, class> |
157 | struct __transform_view_iterator_category_base {}; |
158 | |
159 | template <forward_range _View, class _Fn> |
160 | struct __transform_view_iterator_category_base<_View, _Fn> { |
161 | using _Cat = typename iterator_traits<iterator_t<_View>>::iterator_category; |
162 | |
163 | using iterator_category = |
164 | conditional_t< is_reference_v<invoke_result_t<_Fn&, range_reference_t<_View>>>, |
165 | conditional_t< derived_from<_Cat, contiguous_iterator_tag>, random_access_iterator_tag, _Cat >, |
166 | input_iterator_tag >; |
167 | }; |
168 | |
169 | # if _LIBCPP_STD_VER >= 23 |
170 | template <input_range _View, move_constructible _Fn> |
171 | # else |
172 | template <input_range _View, copy_constructible _Fn> |
173 | # endif |
174 | requires __transform_view_constraints<_View, _Fn> |
175 | template <bool _Const> |
176 | class transform_view<_View, _Fn>::__iterator : public __transform_view_iterator_category_base<_View, _Fn> { |
177 | |
178 | using _Parent = __maybe_const<_Const, transform_view>; |
179 | using _Base = __maybe_const<_Const, _View>; |
180 | |
181 | _Parent* __parent_ = nullptr; |
182 | |
183 | template <bool> |
184 | friend class transform_view<_View, _Fn>::__iterator; |
185 | |
186 | template <bool> |
187 | friend class transform_view<_View, _Fn>::__sentinel; |
188 | |
189 | public: |
190 | iterator_t<_Base> __current_ = iterator_t<_Base>(); |
191 | |
192 | using iterator_concept = typename __transform_view_iterator_concept<_View>::type; |
193 | using value_type = remove_cvref_t<invoke_result_t<_Fn&, range_reference_t<_Base>>>; |
194 | using difference_type = range_difference_t<_Base>; |
195 | |
196 | _LIBCPP_HIDE_FROM_ABI __iterator() |
197 | requires default_initializable<iterator_t<_Base>> |
198 | = default; |
199 | |
200 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator(_Parent& __parent, iterator_t<_Base> __current) |
201 | : __parent_(std::addressof(__parent)), __current_(std::move(__current)) {} |
202 | |
203 | // Note: `__i` should always be `__iterator<false>`, but directly using |
204 | // `__iterator<false>` is ill-formed when `_Const` is false |
205 | // (see http://wg21.link/class.copy.ctor#5). |
206 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i) |
207 | requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>> |
208 | : __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {} |
209 | |
210 | _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept { return __current_; } |
211 | |
212 | _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() && { return std::move(__current_); } |
213 | |
214 | _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const |
215 | noexcept(noexcept(std::invoke(*__parent_->__func_, *__current_))) { |
216 | return std::invoke(*__parent_->__func_, *__current_); |
217 | } |
218 | |
219 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { |
220 | ++__current_; |
221 | return *this; |
222 | } |
223 | |
224 | _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++__current_; } |
225 | |
226 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) |
227 | requires forward_range<_Base> |
228 | { |
229 | auto __tmp = *this; |
230 | ++*this; |
231 | return __tmp; |
232 | } |
233 | |
234 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() |
235 | requires bidirectional_range<_Base> |
236 | { |
237 | --__current_; |
238 | return *this; |
239 | } |
240 | |
241 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) |
242 | requires bidirectional_range<_Base> |
243 | { |
244 | auto __tmp = *this; |
245 | --*this; |
246 | return __tmp; |
247 | } |
248 | |
249 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n) |
250 | requires random_access_range<_Base> |
251 | { |
252 | __current_ += __n; |
253 | return *this; |
254 | } |
255 | |
256 | _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n) |
257 | requires random_access_range<_Base> |
258 | { |
259 | __current_ -= __n; |
260 | return *this; |
261 | } |
262 | |
263 | _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const |
264 | noexcept(noexcept(std::invoke(*__parent_->__func_, __current_[__n]))) |
265 | requires random_access_range<_Base> |
266 | { |
267 | return std::invoke(*__parent_->__func_, __current_[__n]); |
268 | } |
269 | |
270 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) |
271 | requires equality_comparable<iterator_t<_Base>> |
272 | { |
273 | return __x.__current_ == __y.__current_; |
274 | } |
275 | |
276 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) |
277 | requires random_access_range<_Base> |
278 | { |
279 | return __x.__current_ < __y.__current_; |
280 | } |
281 | |
282 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) |
283 | requires random_access_range<_Base> |
284 | { |
285 | return __x.__current_ > __y.__current_; |
286 | } |
287 | |
288 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) |
289 | requires random_access_range<_Base> |
290 | { |
291 | return __x.__current_ <= __y.__current_; |
292 | } |
293 | |
294 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) |
295 | requires random_access_range<_Base> |
296 | { |
297 | return __x.__current_ >= __y.__current_; |
298 | } |
299 | |
300 | _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) |
301 | requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>> |
302 | { |
303 | return __x.__current_ <=> __y.__current_; |
304 | } |
305 | |
306 | _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(__iterator __i, difference_type __n) |
307 | requires random_access_range<_Base> |
308 | { |
309 | return __iterator{*__i.__parent_, __i.__current_ + __n}; |
310 | } |
311 | |
312 | _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, __iterator __i) |
313 | requires random_access_range<_Base> |
314 | { |
315 | return __iterator{*__i.__parent_, __i.__current_ + __n}; |
316 | } |
317 | |
318 | _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(__iterator __i, difference_type __n) |
319 | requires random_access_range<_Base> |
320 | { |
321 | return __iterator{*__i.__parent_, __i.__current_ - __n}; |
322 | } |
323 | |
324 | _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) |
325 | requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>> |
326 | { |
327 | return __x.__current_ - __y.__current_; |
328 | } |
329 | }; |
330 | |
331 | # if _LIBCPP_STD_VER >= 23 |
332 | template <input_range _View, move_constructible _Fn> |
333 | # else |
334 | template <input_range _View, copy_constructible _Fn> |
335 | # endif |
336 | requires __transform_view_constraints<_View, _Fn> |
337 | template <bool _Const> |
338 | class transform_view<_View, _Fn>::__sentinel { |
339 | using _Parent = __maybe_const<_Const, transform_view>; |
340 | using _Base = __maybe_const<_Const, _View>; |
341 | |
342 | sentinel_t<_Base> __end_ = sentinel_t<_Base>(); |
343 | |
344 | template <bool> |
345 | friend class transform_view<_View, _Fn>::__iterator; |
346 | |
347 | template <bool> |
348 | friend class transform_view<_View, _Fn>::__sentinel; |
349 | |
350 | public: |
351 | _LIBCPP_HIDE_FROM_ABI __sentinel() = default; |
352 | |
353 | _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(__end) {} |
354 | |
355 | // Note: `__i` should always be `__sentinel<false>`, but directly using |
356 | // `__sentinel<false>` is ill-formed when `_Const` is false |
357 | // (see http://wg21.link/class.copy.ctor#5). |
358 | _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __i) |
359 | requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>> |
360 | : __end_(std::move(__i.__end_)) {} |
361 | |
362 | _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; } |
363 | |
364 | template <bool _OtherConst> |
365 | requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> |
366 | _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { |
367 | return __x.__current_ == __y.__end_; |
368 | } |
369 | |
370 | template <bool _OtherConst> |
371 | requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> |
372 | _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> |
373 | operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { |
374 | return __x.__current_ - __y.__end_; |
375 | } |
376 | |
377 | template <bool _OtherConst> |
378 | requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>> |
379 | _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>> |
380 | operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) { |
381 | return __x.__end_ - __y.__current_; |
382 | } |
383 | }; |
384 | |
385 | namespace views { |
386 | namespace __transform { |
387 | struct __fn { |
388 | template <class _Range, class _Fn> |
389 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range, _Fn&& __f) const |
390 | noexcept(noexcept(transform_view(std::forward<_Range>(__range), std::forward<_Fn>(__f)))) |
391 | -> decltype(transform_view(std::forward<_Range>(__range), std::forward<_Fn>(__f))) { |
392 | return transform_view(std::forward<_Range>(__range), std::forward<_Fn>(__f)); |
393 | } |
394 | |
395 | template <class _Fn> |
396 | requires constructible_from<decay_t<_Fn>, _Fn> |
397 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Fn&& __f) const |
398 | noexcept(is_nothrow_constructible_v<decay_t<_Fn>, _Fn>) { |
399 | return __range_adaptor_closure_t(std::__bind_back(*this, std::forward<_Fn>(__f))); |
400 | } |
401 | }; |
402 | } // namespace __transform |
403 | |
404 | inline namespace __cpo { |
405 | inline constexpr auto transform = __transform::__fn{}; |
406 | } // namespace __cpo |
407 | } // namespace views |
408 | |
409 | } // namespace ranges |
410 | |
411 | #endif // _LIBCPP_STD_VER >= 20 |
412 | |
413 | _LIBCPP_END_NAMESPACE_STD |
414 | |
415 | _LIBCPP_POP_MACROS |
416 | |
417 | #endif // _LIBCPP___RANGES_TRANSFORM_VIEW_H |
418 | |