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