xref: /freebsd/contrib/llvm-project/libcxx/include/__ranges/elements_view.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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>
19*0fca6ea1SDimitry Andric #include <__fwd/complex.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>
2906c3fb27SDimitry Andric #include <__tuple/tuple_element.h>
3006c3fb27SDimitry Andric #include <__tuple/tuple_like.h>
3106c3fb27SDimitry 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 
46b3edf446SDimitry Andric _LIBCPP_PUSH_MACROS
47b3edf446SDimitry Andric #include <__undef_macros>
48b3edf446SDimitry Andric 
49bdd1243dSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
50bdd1243dSDimitry Andric 
51bdd1243dSDimitry Andric #if _LIBCPP_STD_VER >= 20
52bdd1243dSDimitry Andric 
53bdd1243dSDimitry Andric namespace ranges {
54bdd1243dSDimitry Andric 
55bdd1243dSDimitry Andric template <class _Tp, size_t _Np>
56bdd1243dSDimitry Andric concept __has_tuple_element = __tuple_like<_Tp> && _Np < tuple_size<_Tp>::value;
57bdd1243dSDimitry Andric 
58bdd1243dSDimitry Andric template <class _Tp, size_t _Np>
59bdd1243dSDimitry Andric concept __returnable_element = is_reference_v<_Tp> || move_constructible<tuple_element_t<_Np, _Tp>>;
60bdd1243dSDimitry Andric 
61bdd1243dSDimitry Andric template <input_range _View, size_t _Np>
62bdd1243dSDimitry Andric   requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> &&
63bdd1243dSDimitry Andric            __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> &&
64bdd1243dSDimitry Andric            __returnable_element<range_reference_t<_View>, _Np>
65bdd1243dSDimitry Andric class elements_view : public view_interface<elements_view<_View, _Np>> {
661ac55f4cSDimitry Andric private:
671ac55f4cSDimitry Andric   template <bool>
681ac55f4cSDimitry Andric   class __iterator;
691ac55f4cSDimitry Andric 
701ac55f4cSDimitry Andric   template <bool>
711ac55f4cSDimitry Andric   class __sentinel;
721ac55f4cSDimitry Andric 
73bdd1243dSDimitry Andric public:
74bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI elements_view()
75bdd1243dSDimitry Andric     requires default_initializable<_View>
76bdd1243dSDimitry Andric   = default;
77bdd1243dSDimitry Andric 
elements_view(_View __base)78bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit elements_view(_View __base) : __base_(std::move(__base)) {}
79bdd1243dSDimitry Andric 
base()80bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
81bdd1243dSDimitry Andric     requires copy_constructible<_View>
82bdd1243dSDimitry Andric   {
83bdd1243dSDimitry Andric     return __base_;
84bdd1243dSDimitry Andric   }
85bdd1243dSDimitry Andric 
base()86bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
87bdd1243dSDimitry Andric 
begin()88bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto begin()
89bdd1243dSDimitry Andric     requires(!__simple_view<_View>)
90bdd1243dSDimitry Andric   {
91bdd1243dSDimitry Andric     return __iterator</*_Const=*/false>(ranges::begin(__base_));
92bdd1243dSDimitry Andric   }
93bdd1243dSDimitry Andric 
begin()94bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
95bdd1243dSDimitry Andric     requires range<const _View>
96bdd1243dSDimitry Andric   {
97bdd1243dSDimitry Andric     return __iterator</*_Const=*/true>(ranges::begin(__base_));
98bdd1243dSDimitry Andric   }
99bdd1243dSDimitry Andric 
end()100bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto end()
101bdd1243dSDimitry Andric     requires(!__simple_view<_View> && !common_range<_View>)
102bdd1243dSDimitry Andric   {
103bdd1243dSDimitry Andric     return __sentinel</*_Const=*/false>{ranges::end(__base_)};
104bdd1243dSDimitry Andric   }
105bdd1243dSDimitry Andric 
end()106bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto end()
107bdd1243dSDimitry Andric     requires(!__simple_view<_View> && common_range<_View>)
108bdd1243dSDimitry Andric   {
109bdd1243dSDimitry Andric     return __iterator</*_Const=*/false>{ranges::end(__base_)};
110bdd1243dSDimitry Andric   }
111bdd1243dSDimitry Andric 
end()112bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
113bdd1243dSDimitry Andric     requires range<const _View>
114bdd1243dSDimitry Andric   {
115bdd1243dSDimitry Andric     return __sentinel</*_Const=*/true>{ranges::end(__base_)};
116bdd1243dSDimitry Andric   }
117bdd1243dSDimitry Andric 
end()118bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
119bdd1243dSDimitry Andric     requires common_range<const _View>
120bdd1243dSDimitry Andric   {
121bdd1243dSDimitry Andric     return __iterator</*_Const=*/true>{ranges::end(__base_)};
122bdd1243dSDimitry Andric   }
123bdd1243dSDimitry Andric 
size()124bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto size()
125bdd1243dSDimitry Andric     requires sized_range<_View>
126bdd1243dSDimitry Andric   {
127bdd1243dSDimitry Andric     return ranges::size(__base_);
128bdd1243dSDimitry Andric   }
129bdd1243dSDimitry Andric 
size()130bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
131bdd1243dSDimitry Andric     requires sized_range<const _View>
132bdd1243dSDimitry Andric   {
133bdd1243dSDimitry Andric     return ranges::size(__base_);
134bdd1243dSDimitry Andric   }
135bdd1243dSDimitry Andric 
136bdd1243dSDimitry Andric private:
137bdd1243dSDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
138bdd1243dSDimitry Andric };
139bdd1243dSDimitry Andric 
140bdd1243dSDimitry Andric template <class, size_t>
141bdd1243dSDimitry Andric struct __elements_view_iterator_category_base {};
142bdd1243dSDimitry Andric 
143bdd1243dSDimitry Andric template <forward_range _Base, size_t _Np>
144bdd1243dSDimitry Andric struct __elements_view_iterator_category_base<_Base, _Np> {
145bdd1243dSDimitry Andric   static consteval auto __get_iterator_category() {
146bdd1243dSDimitry Andric     using _Result = decltype(std::get<_Np>(*std::declval<iterator_t<_Base>>()));
147bdd1243dSDimitry Andric     using _Cat    = typename iterator_traits<iterator_t<_Base>>::iterator_category;
148bdd1243dSDimitry Andric 
149bdd1243dSDimitry Andric     if constexpr (!is_lvalue_reference_v<_Result>) {
150bdd1243dSDimitry Andric       return input_iterator_tag{};
151bdd1243dSDimitry Andric     } else if constexpr (derived_from<_Cat, random_access_iterator_tag>) {
152bdd1243dSDimitry Andric       return random_access_iterator_tag{};
153bdd1243dSDimitry Andric     } else {
154bdd1243dSDimitry Andric       return _Cat{};
155bdd1243dSDimitry Andric     }
156bdd1243dSDimitry Andric   }
157bdd1243dSDimitry Andric 
158bdd1243dSDimitry Andric   using iterator_category = decltype(__get_iterator_category());
159bdd1243dSDimitry Andric };
160bdd1243dSDimitry Andric 
1611ac55f4cSDimitry Andric template <input_range _View, size_t _Np>
1621ac55f4cSDimitry Andric   requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> &&
1631ac55f4cSDimitry Andric            __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> &&
1641ac55f4cSDimitry Andric            __returnable_element<range_reference_t<_View>, _Np>
1651ac55f4cSDimitry Andric template <bool _Const>
1661ac55f4cSDimitry Andric class elements_view<_View, _Np>::__iterator
1671ac55f4cSDimitry Andric     : public __elements_view_iterator_category_base<__maybe_const<_Const, _View>, _Np> {
1681ac55f4cSDimitry Andric   template <bool>
1691ac55f4cSDimitry Andric   friend class __iterator;
170bdd1243dSDimitry Andric 
1711ac55f4cSDimitry Andric   template <bool>
1721ac55f4cSDimitry Andric   friend class __sentinel;
173bdd1243dSDimitry Andric 
174bdd1243dSDimitry Andric   using _Base = __maybe_const<_Const, _View>;
175bdd1243dSDimitry Andric 
176bdd1243dSDimitry Andric   iterator_t<_Base> __current_ = iterator_t<_Base>();
177bdd1243dSDimitry Andric 
178bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_element(const iterator_t<_Base>& __i) {
179bdd1243dSDimitry Andric     if constexpr (is_reference_v<range_reference_t<_Base>>) {
180bdd1243dSDimitry Andric       return std::get<_Np>(*__i);
181bdd1243dSDimitry Andric     } else {
182bdd1243dSDimitry Andric       using _Element = remove_cv_t<tuple_element_t<_Np, range_reference_t<_Base>>>;
183bdd1243dSDimitry Andric       return static_cast<_Element>(std::get<_Np>(*__i));
184bdd1243dSDimitry Andric     }
185bdd1243dSDimitry Andric   }
186bdd1243dSDimitry Andric 
187bdd1243dSDimitry Andric   static consteval auto __get_iterator_concept() {
188bdd1243dSDimitry Andric     if constexpr (random_access_range<_Base>) {
189bdd1243dSDimitry Andric       return random_access_iterator_tag{};
190bdd1243dSDimitry Andric     } else if constexpr (bidirectional_range<_Base>) {
191bdd1243dSDimitry Andric       return bidirectional_iterator_tag{};
192bdd1243dSDimitry Andric     } else if constexpr (forward_range<_Base>) {
193bdd1243dSDimitry Andric       return forward_iterator_tag{};
194bdd1243dSDimitry Andric     } else {
195bdd1243dSDimitry Andric       return input_iterator_tag{};
196bdd1243dSDimitry Andric     }
197bdd1243dSDimitry Andric   }
198bdd1243dSDimitry Andric 
199bdd1243dSDimitry Andric public:
200bdd1243dSDimitry Andric   using iterator_concept = decltype(__get_iterator_concept());
201bdd1243dSDimitry Andric   using value_type       = remove_cvref_t<tuple_element_t<_Np, range_value_t<_Base>>>;
202bdd1243dSDimitry Andric   using difference_type  = range_difference_t<_Base>;
203bdd1243dSDimitry Andric 
2041ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI __iterator()
205bdd1243dSDimitry Andric     requires default_initializable<iterator_t<_Base>>
206bdd1243dSDimitry Andric   = default;
207bdd1243dSDimitry Andric 
2081ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator(iterator_t<_Base> __current) : __current_(std::move(__current)) {}
209bdd1243dSDimitry Andric 
2101ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i)
211bdd1243dSDimitry Andric     requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>>
212bdd1243dSDimitry Andric       : __current_(std::move(__i.__current_)) {}
213bdd1243dSDimitry Andric 
214bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr const iterator_t<_Base>& base() const& noexcept { return __current_; }
215bdd1243dSDimitry Andric 
216bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Base> base() && { return std::move(__current_); }
217bdd1243dSDimitry Andric 
218bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return __get_element(__current_); }
219bdd1243dSDimitry Andric 
2201ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() {
221bdd1243dSDimitry Andric     ++__current_;
222bdd1243dSDimitry Andric     return *this;
223bdd1243dSDimitry Andric   }
224bdd1243dSDimitry Andric 
225bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++__current_; }
226bdd1243dSDimitry Andric 
2271ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int)
228bdd1243dSDimitry Andric     requires forward_range<_Base>
229bdd1243dSDimitry Andric   {
23006c3fb27SDimitry Andric     auto __temp = *this;
231bdd1243dSDimitry Andric     ++__current_;
23206c3fb27SDimitry Andric     return __temp;
233bdd1243dSDimitry Andric   }
234bdd1243dSDimitry Andric 
2351ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--()
236bdd1243dSDimitry Andric     requires bidirectional_range<_Base>
237bdd1243dSDimitry Andric   {
238bdd1243dSDimitry Andric     --__current_;
239bdd1243dSDimitry Andric     return *this;
240bdd1243dSDimitry Andric   }
241bdd1243dSDimitry Andric 
2421ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int)
243bdd1243dSDimitry Andric     requires bidirectional_range<_Base>
244bdd1243dSDimitry Andric   {
24506c3fb27SDimitry Andric     auto __temp = *this;
246bdd1243dSDimitry Andric     --__current_;
24706c3fb27SDimitry Andric     return __temp;
248bdd1243dSDimitry Andric   }
249bdd1243dSDimitry Andric 
2501ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __n)
251bdd1243dSDimitry Andric     requires random_access_range<_Base>
252bdd1243dSDimitry Andric   {
253bdd1243dSDimitry Andric     __current_ += __n;
254bdd1243dSDimitry Andric     return *this;
255bdd1243dSDimitry Andric   }
256bdd1243dSDimitry Andric 
2571ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __n)
258bdd1243dSDimitry Andric     requires random_access_range<_Base>
259bdd1243dSDimitry Andric   {
260bdd1243dSDimitry Andric     __current_ -= __n;
261bdd1243dSDimitry Andric     return *this;
262bdd1243dSDimitry Andric   }
263bdd1243dSDimitry Andric 
264bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const
265bdd1243dSDimitry Andric     requires random_access_range<_Base>
266bdd1243dSDimitry Andric   {
267bdd1243dSDimitry Andric     return __get_element(__current_ + __n);
268bdd1243dSDimitry Andric   }
269bdd1243dSDimitry Andric 
2701ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
271bdd1243dSDimitry Andric     requires equality_comparable<iterator_t<_Base>>
272bdd1243dSDimitry Andric   {
273bdd1243dSDimitry Andric     return __x.__current_ == __y.__current_;
274bdd1243dSDimitry Andric   }
275bdd1243dSDimitry Andric 
2761ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
277bdd1243dSDimitry Andric     requires random_access_range<_Base>
278bdd1243dSDimitry Andric   {
279bdd1243dSDimitry Andric     return __x.__current_ < __y.__current_;
280bdd1243dSDimitry Andric   }
281bdd1243dSDimitry Andric 
2821ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
283bdd1243dSDimitry Andric     requires random_access_range<_Base>
284bdd1243dSDimitry Andric   {
285bdd1243dSDimitry Andric     return __y < __x;
286bdd1243dSDimitry Andric   }
287bdd1243dSDimitry Andric 
2881ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
289bdd1243dSDimitry Andric     requires random_access_range<_Base>
290bdd1243dSDimitry Andric   {
291bdd1243dSDimitry Andric     return !(__y < __x);
292bdd1243dSDimitry Andric   }
293bdd1243dSDimitry Andric 
2941ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
295bdd1243dSDimitry Andric     requires random_access_range<_Base>
296bdd1243dSDimitry Andric   {
297bdd1243dSDimitry Andric     return !(__x < __y);
298bdd1243dSDimitry Andric   }
299bdd1243dSDimitry Andric 
3001ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
301bdd1243dSDimitry Andric     requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>>
302bdd1243dSDimitry Andric   {
303bdd1243dSDimitry Andric     return __x.__current_ <=> __y.__current_;
304bdd1243dSDimitry Andric   }
305bdd1243dSDimitry Andric 
3061ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __x, difference_type __y)
307bdd1243dSDimitry Andric     requires random_access_range<_Base>
308bdd1243dSDimitry Andric   {
3091ac55f4cSDimitry Andric     return __iterator{__x} += __y;
310bdd1243dSDimitry Andric   }
311bdd1243dSDimitry Andric 
3121ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __x, const __iterator& __y)
313bdd1243dSDimitry Andric     requires random_access_range<_Base>
314bdd1243dSDimitry Andric   {
315bdd1243dSDimitry Andric     return __y + __x;
316bdd1243dSDimitry Andric   }
317bdd1243dSDimitry Andric 
3181ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __x, difference_type __y)
319bdd1243dSDimitry Andric     requires random_access_range<_Base>
320bdd1243dSDimitry Andric   {
3211ac55f4cSDimitry Andric     return __iterator{__x} -= __y;
322bdd1243dSDimitry Andric   }
323bdd1243dSDimitry Andric 
3241ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y)
325bdd1243dSDimitry Andric     requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>>
326bdd1243dSDimitry Andric   {
327bdd1243dSDimitry Andric     return __x.__current_ - __y.__current_;
328bdd1243dSDimitry Andric   }
329bdd1243dSDimitry Andric };
330bdd1243dSDimitry Andric 
3311ac55f4cSDimitry Andric template <input_range _View, size_t _Np>
3321ac55f4cSDimitry Andric   requires view<_View> && __has_tuple_element<range_value_t<_View>, _Np> &&
3331ac55f4cSDimitry Andric            __has_tuple_element<remove_reference_t<range_reference_t<_View>>, _Np> &&
3341ac55f4cSDimitry Andric            __returnable_element<range_reference_t<_View>, _Np>
3351ac55f4cSDimitry Andric template <bool _Const>
3361ac55f4cSDimitry Andric class elements_view<_View, _Np>::__sentinel {
337bdd1243dSDimitry Andric private:
338bdd1243dSDimitry Andric   using _Base                                        = __maybe_const<_Const, _View>;
339bdd1243dSDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS sentinel_t<_Base> __end_ = sentinel_t<_Base>();
340bdd1243dSDimitry Andric 
3411ac55f4cSDimitry Andric   template <bool>
3421ac55f4cSDimitry Andric   friend class __sentinel;
343bdd1243dSDimitry Andric 
344bdd1243dSDimitry Andric   template <bool _AnyConst>
3451ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) __get_current(const __iterator<_AnyConst>& __iter) {
346bdd1243dSDimitry Andric     return (__iter.__current_);
347bdd1243dSDimitry Andric   }
348bdd1243dSDimitry Andric 
349bdd1243dSDimitry Andric public:
3501ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI __sentinel() = default;
351bdd1243dSDimitry Andric 
3521ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(std::move(__end)) {}
353bdd1243dSDimitry Andric 
3541ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __other)
355bdd1243dSDimitry Andric     requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
356bdd1243dSDimitry Andric       : __end_(std::move(__other.__end_)) {}
357bdd1243dSDimitry Andric 
358bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Base> base() const { return __end_; }
359bdd1243dSDimitry Andric 
360bdd1243dSDimitry Andric   template <bool _OtherConst>
361bdd1243dSDimitry Andric     requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
3621ac55f4cSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
363bdd1243dSDimitry Andric     return __get_current(__x) == __y.__end_;
364bdd1243dSDimitry Andric   }
365bdd1243dSDimitry Andric 
366bdd1243dSDimitry Andric   template <bool _OtherConst>
367bdd1243dSDimitry Andric     requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
368bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
3691ac55f4cSDimitry Andric   operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
370bdd1243dSDimitry Andric     return __get_current(__x) - __y.__end_;
371bdd1243dSDimitry Andric   }
372bdd1243dSDimitry Andric 
373bdd1243dSDimitry Andric   template <bool _OtherConst>
374bdd1243dSDimitry Andric     requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
375bdd1243dSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
3761ac55f4cSDimitry Andric   operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) {
377bdd1243dSDimitry Andric     return __x.__end_ - __get_current(__y);
378bdd1243dSDimitry Andric   }
379bdd1243dSDimitry Andric };
380bdd1243dSDimitry Andric 
381bdd1243dSDimitry Andric template <class _Tp, size_t _Np>
382bdd1243dSDimitry Andric inline constexpr bool enable_borrowed_range<elements_view<_Tp, _Np>> = enable_borrowed_range<_Tp>;
383bdd1243dSDimitry Andric 
384bdd1243dSDimitry Andric template <class _Tp>
385bdd1243dSDimitry Andric using keys_view = elements_view<_Tp, 0>;
386bdd1243dSDimitry Andric template <class _Tp>
387bdd1243dSDimitry Andric using values_view = elements_view<_Tp, 1>;
388bdd1243dSDimitry Andric 
389bdd1243dSDimitry Andric namespace views {
390bdd1243dSDimitry Andric namespace __elements {
391bdd1243dSDimitry Andric 
392bdd1243dSDimitry Andric template <size_t _Np>
393bdd1243dSDimitry Andric struct __fn : __range_adaptor_closure<__fn<_Np>> {
394bdd1243dSDimitry Andric   template <class _Range>
395bdd1243dSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Range&& __range) const
396bdd1243dSDimitry Andric       /**/ noexcept(noexcept(elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range))))
397bdd1243dSDimitry Andric       /*------*/ -> decltype(elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range))) {
398bdd1243dSDimitry Andric     /*-------------*/ return elements_view<all_t<_Range&&>, _Np>(std::forward<_Range>(__range));
399bdd1243dSDimitry Andric   }
400bdd1243dSDimitry Andric };
401bdd1243dSDimitry Andric } // namespace __elements
402bdd1243dSDimitry Andric 
403bdd1243dSDimitry Andric inline namespace __cpo {
404bdd1243dSDimitry Andric template <size_t _Np>
405bdd1243dSDimitry Andric inline constexpr auto elements = __elements::__fn<_Np>{};
406bdd1243dSDimitry Andric inline constexpr auto keys     = elements<0>;
407bdd1243dSDimitry Andric inline constexpr auto values   = elements<1>;
408bdd1243dSDimitry Andric } // namespace __cpo
409bdd1243dSDimitry Andric } // namespace views
410bdd1243dSDimitry Andric } // namespace ranges
411bdd1243dSDimitry Andric 
412bdd1243dSDimitry Andric #endif // _LIBCPP_STD_VER >= 20
413bdd1243dSDimitry Andric 
414bdd1243dSDimitry Andric _LIBCPP_END_NAMESPACE_STD
415bdd1243dSDimitry Andric 
416b3edf446SDimitry Andric _LIBCPP_POP_MACROS
417b3edf446SDimitry Andric 
418bdd1243dSDimitry Andric #endif // _LIBCPP___RANGES_ELEMENTS_VIEW_H
419