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