xref: /freebsd-src/contrib/llvm-project/libcxx/include/__ranges/access.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1fe6060f1SDimitry Andric // -*- C++ -*-
2349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
3fe6060f1SDimitry Andric //
4fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7fe6060f1SDimitry Andric //
8fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
9bdd1243dSDimitry Andric 
10fe6060f1SDimitry Andric #ifndef _LIBCPP___RANGES_ACCESS_H
11fe6060f1SDimitry Andric #define _LIBCPP___RANGES_ACCESS_H
12fe6060f1SDimitry Andric 
1304eeddc0SDimitry Andric #include <__concepts/class_or_enum.h>
14fe6060f1SDimitry Andric #include <__config>
15fe6060f1SDimitry Andric #include <__iterator/concepts.h>
16fe6060f1SDimitry Andric #include <__iterator/readable_traits.h>
17fe6060f1SDimitry Andric #include <__ranges/enable_borrowed_range.h>
18bdd1243dSDimitry Andric #include <__type_traits/decay.h>
19bdd1243dSDimitry Andric #include <__type_traits/is_reference.h>
20bdd1243dSDimitry Andric #include <__type_traits/remove_cvref.h>
21bdd1243dSDimitry Andric #include <__type_traits/remove_reference.h>
220eae32dcSDimitry Andric #include <__utility/auto_cast.h>
23bdd1243dSDimitry Andric #include <__utility/declval.h>
24bdd1243dSDimitry Andric #include <cstddef>
25fe6060f1SDimitry Andric 
26fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
27fe6060f1SDimitry Andric #  pragma GCC system_header
28fe6060f1SDimitry Andric #endif
29fe6060f1SDimitry Andric 
30fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
31fe6060f1SDimitry Andric 
3206c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
33fe6060f1SDimitry Andric 
34fe6060f1SDimitry Andric namespace ranges {
35fe6060f1SDimitry Andric template <class _Tp>
36cb14a3feSDimitry Andric concept __can_borrow = is_lvalue_reference_v<_Tp> || enable_borrowed_range<remove_cvref_t<_Tp>>;
37fe6060f1SDimitry Andric } // namespace ranges
38fe6060f1SDimitry Andric 
39fe6060f1SDimitry Andric // [range.access.begin]
400eae32dcSDimitry Andric 
410eae32dcSDimitry Andric namespace ranges {
420eae32dcSDimitry Andric namespace __begin {
43fe6060f1SDimitry Andric template <class _Tp>
44*0fca6ea1SDimitry Andric concept __member_begin = __can_borrow<_Tp> && requires(_Tp&& __t) {
450eae32dcSDimitry Andric   { _LIBCPP_AUTO_CAST(__t.begin()) } -> input_or_output_iterator;
46fe6060f1SDimitry Andric };
47fe6060f1SDimitry Andric 
48*0fca6ea1SDimitry Andric void begin() = delete;
49fe6060f1SDimitry Andric 
50fe6060f1SDimitry Andric template <class _Tp>
51fe6060f1SDimitry Andric concept __unqualified_begin =
52cb14a3feSDimitry Andric     !__member_begin<_Tp> && __can_borrow<_Tp> && __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) {
530eae32dcSDimitry Andric       { _LIBCPP_AUTO_CAST(begin(__t)) } -> input_or_output_iterator;
54fe6060f1SDimitry Andric     };
55fe6060f1SDimitry Andric 
56fe6060f1SDimitry Andric struct __fn {
57fe6060f1SDimitry Andric   template <class _Tp>
581838bd0fSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[]) const noexcept
5981ad6265SDimitry Andric     requires(sizeof(_Tp) >= 0) // Disallow incomplete element types.
600eae32dcSDimitry Andric   {
611838bd0fSDimitry Andric     return __t + 0;
621838bd0fSDimitry Andric   }
631838bd0fSDimitry Andric 
641838bd0fSDimitry Andric   template <class _Tp, size_t _Np>
651838bd0fSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept
6681ad6265SDimitry Andric     requires(sizeof(_Tp) >= 0) // Disallow incomplete element types.
671838bd0fSDimitry Andric   {
681838bd0fSDimitry Andric     return __t + 0;
69fe6060f1SDimitry Andric   }
70fe6060f1SDimitry Andric 
71fe6060f1SDimitry Andric   template <class _Tp>
72fe6060f1SDimitry Andric     requires __member_begin<_Tp>
73fe6060f1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
74cb14a3feSDimitry Andric       noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.begin()))) {
750eae32dcSDimitry Andric     return _LIBCPP_AUTO_CAST(__t.begin());
76fe6060f1SDimitry Andric   }
77fe6060f1SDimitry Andric 
78fe6060f1SDimitry Andric   template <class _Tp>
79fe6060f1SDimitry Andric     requires __unqualified_begin<_Tp>
80fe6060f1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
81cb14a3feSDimitry Andric       noexcept(noexcept(_LIBCPP_AUTO_CAST(begin(__t)))) {
820eae32dcSDimitry Andric     return _LIBCPP_AUTO_CAST(begin(__t));
83fe6060f1SDimitry Andric   }
84fe6060f1SDimitry Andric 
85fe6060f1SDimitry Andric   void operator()(auto&&) const = delete;
86fe6060f1SDimitry Andric };
871fd87a68SDimitry Andric } // namespace __begin
88fe6060f1SDimitry Andric 
89fe6060f1SDimitry Andric inline namespace __cpo {
90fe6060f1SDimitry Andric inline constexpr auto begin = __begin::__fn{};
91fe6060f1SDimitry Andric } // namespace __cpo
920eae32dcSDimitry Andric } // namespace ranges
93fe6060f1SDimitry Andric 
940eae32dcSDimitry Andric // [range.range]
950eae32dcSDimitry Andric 
960eae32dcSDimitry Andric namespace ranges {
97fe6060f1SDimitry Andric template <class _Tp>
98bdd1243dSDimitry Andric using iterator_t = decltype(ranges::begin(std::declval<_Tp&>()));
99fe6060f1SDimitry Andric } // namespace ranges
100fe6060f1SDimitry Andric 
101fe6060f1SDimitry Andric // [range.access.end]
1020eae32dcSDimitry Andric 
1030eae32dcSDimitry Andric namespace ranges {
1040eae32dcSDimitry Andric namespace __end {
105fe6060f1SDimitry Andric template <class _Tp>
106*0fca6ea1SDimitry Andric concept __member_end = __can_borrow<_Tp> && requires(_Tp&& __t) {
107fe6060f1SDimitry Andric   typename iterator_t<_Tp>;
1080eae32dcSDimitry Andric   { _LIBCPP_AUTO_CAST(__t.end()) } -> sentinel_for<iterator_t<_Tp>>;
109fe6060f1SDimitry Andric };
110fe6060f1SDimitry Andric 
111*0fca6ea1SDimitry Andric void end() = delete;
112fe6060f1SDimitry Andric 
113fe6060f1SDimitry Andric template <class _Tp>
114fe6060f1SDimitry Andric concept __unqualified_end =
115cb14a3feSDimitry Andric     !__member_end<_Tp> && __can_borrow<_Tp> && __class_or_enum<remove_cvref_t<_Tp>> && requires(_Tp&& __t) {
116fe6060f1SDimitry Andric       typename iterator_t<_Tp>;
1170eae32dcSDimitry Andric       { _LIBCPP_AUTO_CAST(end(__t)) } -> sentinel_for<iterator_t<_Tp>>;
118fe6060f1SDimitry Andric     };
119fe6060f1SDimitry Andric 
12081ad6265SDimitry Andric struct __fn {
121fe6060f1SDimitry Andric   template <class _Tp, size_t _Np>
1220eae32dcSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept
12381ad6265SDimitry Andric     requires(sizeof(_Tp) >= 0) // Disallow incomplete element types.
1240eae32dcSDimitry Andric   {
125fe6060f1SDimitry Andric     return __t + _Np;
126fe6060f1SDimitry Andric   }
127fe6060f1SDimitry Andric 
128fe6060f1SDimitry Andric   template <class _Tp>
129fe6060f1SDimitry Andric     requires __member_end<_Tp>
130fe6060f1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
131cb14a3feSDimitry Andric       noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.end()))) {
1320eae32dcSDimitry Andric     return _LIBCPP_AUTO_CAST(__t.end());
133fe6060f1SDimitry Andric   }
134fe6060f1SDimitry Andric 
135fe6060f1SDimitry Andric   template <class _Tp>
136fe6060f1SDimitry Andric     requires __unqualified_end<_Tp>
137fe6060f1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
138cb14a3feSDimitry Andric       noexcept(noexcept(_LIBCPP_AUTO_CAST(end(__t)))) {
1390eae32dcSDimitry Andric     return _LIBCPP_AUTO_CAST(end(__t));
140fe6060f1SDimitry Andric   }
141fe6060f1SDimitry Andric 
142fe6060f1SDimitry Andric   void operator()(auto&&) const = delete;
143fe6060f1SDimitry Andric };
1441fd87a68SDimitry Andric } // namespace __end
145fe6060f1SDimitry Andric 
1460eae32dcSDimitry Andric inline namespace __cpo {
147fe6060f1SDimitry Andric inline constexpr auto end = __end::__fn{};
1480eae32dcSDimitry Andric } // namespace __cpo
1490eae32dcSDimitry Andric } // namespace ranges
150fe6060f1SDimitry Andric 
1510eae32dcSDimitry Andric // [range.access.cbegin]
1520eae32dcSDimitry Andric 
1530eae32dcSDimitry Andric namespace ranges {
1540eae32dcSDimitry Andric namespace __cbegin {
155fe6060f1SDimitry Andric struct __fn {
156fe6060f1SDimitry Andric   template <class _Tp>
15704eeddc0SDimitry Andric     requires is_lvalue_reference_v<_Tp&&>
158cb14a3feSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
15904eeddc0SDimitry Andric       noexcept(noexcept(ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t))))
160cb14a3feSDimitry Andric           -> decltype(ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t))) {
161cb14a3feSDimitry Andric     return ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t));
162cb14a3feSDimitry Andric   }
163fe6060f1SDimitry Andric 
164fe6060f1SDimitry Andric   template <class _Tp>
16504eeddc0SDimitry Andric     requires is_rvalue_reference_v<_Tp&&>
166cb14a3feSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
16704eeddc0SDimitry Andric       noexcept(noexcept(ranges::begin(static_cast<const _Tp&&>(__t))))
168cb14a3feSDimitry Andric           -> decltype(ranges::begin(static_cast<const _Tp&&>(__t))) {
169cb14a3feSDimitry Andric     return ranges::begin(static_cast<const _Tp&&>(__t));
170cb14a3feSDimitry Andric   }
171fe6060f1SDimitry Andric };
1721fd87a68SDimitry Andric } // namespace __cbegin
173fe6060f1SDimitry Andric 
1740eae32dcSDimitry Andric inline namespace __cpo {
175fe6060f1SDimitry Andric inline constexpr auto cbegin = __cbegin::__fn{};
1760eae32dcSDimitry Andric } // namespace __cpo
1770eae32dcSDimitry Andric } // namespace ranges
178fe6060f1SDimitry Andric 
1790eae32dcSDimitry Andric // [range.access.cend]
1800eae32dcSDimitry Andric 
1810eae32dcSDimitry Andric namespace ranges {
1820eae32dcSDimitry Andric namespace __cend {
183fe6060f1SDimitry Andric struct __fn {
184fe6060f1SDimitry Andric   template <class _Tp>
18504eeddc0SDimitry Andric     requires is_lvalue_reference_v<_Tp&&>
186cb14a3feSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
18704eeddc0SDimitry Andric       noexcept(noexcept(ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t))))
188cb14a3feSDimitry Andric           -> decltype(ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t))) {
189cb14a3feSDimitry Andric     return ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t));
190cb14a3feSDimitry Andric   }
191fe6060f1SDimitry Andric 
192fe6060f1SDimitry Andric   template <class _Tp>
19304eeddc0SDimitry Andric     requires is_rvalue_reference_v<_Tp&&>
194*0fca6ea1SDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const noexcept(
195*0fca6ea1SDimitry Andric       noexcept(ranges::end(static_cast<const _Tp&&>(__t)))) -> decltype(ranges::end(static_cast<const _Tp&&>(__t))) {
196cb14a3feSDimitry Andric     return ranges::end(static_cast<const _Tp&&>(__t));
197cb14a3feSDimitry Andric   }
198fe6060f1SDimitry Andric };
1991fd87a68SDimitry Andric } // namespace __cend
200fe6060f1SDimitry Andric 
2010eae32dcSDimitry Andric inline namespace __cpo {
202fe6060f1SDimitry Andric inline constexpr auto cend = __cend::__fn{};
2030eae32dcSDimitry Andric } // namespace __cpo
2040eae32dcSDimitry Andric } // namespace ranges
205fe6060f1SDimitry Andric 
20606c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 20
207fe6060f1SDimitry Andric 
208fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
209fe6060f1SDimitry Andric 
210fe6060f1SDimitry Andric #endif // _LIBCPP___RANGES_ACCESS_H
211