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