xref: /freebsd-src/contrib/llvm-project/libcxx/include/__ranges/access.h (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
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 //===----------------------------------------------------------------------===//
9fe6060f1SDimitry Andric #ifndef _LIBCPP___RANGES_ACCESS_H
10fe6060f1SDimitry Andric #define _LIBCPP___RANGES_ACCESS_H
11fe6060f1SDimitry Andric 
12*04eeddc0SDimitry Andric #include <__concepts/class_or_enum.h>
13fe6060f1SDimitry Andric #include <__config>
14fe6060f1SDimitry Andric #include <__iterator/concepts.h>
15fe6060f1SDimitry Andric #include <__iterator/readable_traits.h>
16fe6060f1SDimitry Andric #include <__ranges/enable_borrowed_range.h>
17349cc55cSDimitry Andric #include <__utility/as_const.h>
180eae32dcSDimitry Andric #include <__utility/auto_cast.h>
19fe6060f1SDimitry Andric #include <concepts>
20fe6060f1SDimitry Andric #include <type_traits>
21fe6060f1SDimitry Andric 
22fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23fe6060f1SDimitry Andric #pragma GCC system_header
24fe6060f1SDimitry Andric #endif
25fe6060f1SDimitry Andric 
26fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
27fe6060f1SDimitry Andric 
28fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_RANGES)
29fe6060f1SDimitry Andric 
30fe6060f1SDimitry Andric namespace ranges {
31fe6060f1SDimitry Andric   template <class _Tp>
32fe6060f1SDimitry Andric   concept __can_borrow =
33fe6060f1SDimitry Andric     is_lvalue_reference_v<_Tp> || enable_borrowed_range<remove_cvref_t<_Tp>>;
34fe6060f1SDimitry Andric } // namespace ranges
35fe6060f1SDimitry Andric 
36fe6060f1SDimitry Andric // [range.access.begin]
370eae32dcSDimitry Andric 
380eae32dcSDimitry Andric namespace ranges {
390eae32dcSDimitry Andric namespace __begin {
40fe6060f1SDimitry Andric   template <class _Tp>
41fe6060f1SDimitry Andric   concept __member_begin =
42fe6060f1SDimitry Andric     __can_borrow<_Tp> &&
43*04eeddc0SDimitry Andric     __workaround_52970<_Tp> &&
44fe6060f1SDimitry Andric     requires(_Tp&& __t) {
450eae32dcSDimitry Andric       { _LIBCPP_AUTO_CAST(__t.begin()) } -> input_or_output_iterator;
46fe6060f1SDimitry Andric     };
47fe6060f1SDimitry Andric 
48fe6060f1SDimitry Andric   void begin(auto&) = delete;
49fe6060f1SDimitry Andric   void begin(const auto&) = delete;
50fe6060f1SDimitry Andric 
51fe6060f1SDimitry Andric   template <class _Tp>
52fe6060f1SDimitry Andric   concept __unqualified_begin =
53fe6060f1SDimitry Andric     !__member_begin<_Tp> &&
54fe6060f1SDimitry Andric     __can_borrow<_Tp> &&
55fe6060f1SDimitry Andric     __class_or_enum<remove_cvref_t<_Tp>> &&
56fe6060f1SDimitry Andric     requires(_Tp && __t) {
570eae32dcSDimitry Andric       { _LIBCPP_AUTO_CAST(begin(__t)) } -> input_or_output_iterator;
58fe6060f1SDimitry Andric     };
59fe6060f1SDimitry Andric 
60fe6060f1SDimitry Andric   struct __fn {
61fe6060f1SDimitry Andric     template <class _Tp>
62fe6060f1SDimitry Andric       requires is_array_v<remove_cv_t<_Tp>>
630eae32dcSDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __t) const noexcept
640eae32dcSDimitry Andric     {
650eae32dcSDimitry Andric       return __t;
66fe6060f1SDimitry Andric     }
67fe6060f1SDimitry Andric 
68fe6060f1SDimitry Andric     template <class _Tp>
69fe6060f1SDimitry Andric       requires __member_begin<_Tp>
70fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
710eae32dcSDimitry Andric       noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.begin())))
72fe6060f1SDimitry Andric     {
730eae32dcSDimitry Andric       return _LIBCPP_AUTO_CAST(__t.begin());
74fe6060f1SDimitry Andric     }
75fe6060f1SDimitry Andric 
76fe6060f1SDimitry Andric     template <class _Tp>
77fe6060f1SDimitry Andric       requires __unqualified_begin<_Tp>
78fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
790eae32dcSDimitry Andric       noexcept(noexcept(_LIBCPP_AUTO_CAST(begin(__t))))
80fe6060f1SDimitry Andric     {
810eae32dcSDimitry Andric       return _LIBCPP_AUTO_CAST(begin(__t));
82fe6060f1SDimitry Andric     }
83fe6060f1SDimitry Andric 
84fe6060f1SDimitry Andric     void operator()(auto&&) const = delete;
85fe6060f1SDimitry Andric   };
860eae32dcSDimitry Andric }
87fe6060f1SDimitry Andric 
88fe6060f1SDimitry Andric inline namespace __cpo {
89fe6060f1SDimitry Andric   inline constexpr auto begin = __begin::__fn{};
90fe6060f1SDimitry Andric } // namespace __cpo
910eae32dcSDimitry Andric } // namespace ranges
92fe6060f1SDimitry Andric 
930eae32dcSDimitry Andric // [range.range]
940eae32dcSDimitry Andric 
950eae32dcSDimitry Andric namespace ranges {
96fe6060f1SDimitry Andric   template <class _Tp>
97fe6060f1SDimitry Andric   using iterator_t = decltype(ranges::begin(declval<_Tp&>()));
98fe6060f1SDimitry Andric } // namespace ranges
99fe6060f1SDimitry Andric 
100fe6060f1SDimitry Andric // [range.access.end]
1010eae32dcSDimitry Andric 
1020eae32dcSDimitry Andric namespace ranges {
1030eae32dcSDimitry Andric namespace __end {
104fe6060f1SDimitry Andric   template <class _Tp>
105fe6060f1SDimitry Andric   concept __member_end =
106fe6060f1SDimitry Andric     __can_borrow<_Tp> &&
107*04eeddc0SDimitry Andric     __workaround_52970<_Tp> &&
108fe6060f1SDimitry Andric     requires(_Tp&& __t) {
109fe6060f1SDimitry Andric       typename iterator_t<_Tp>;
1100eae32dcSDimitry Andric       { _LIBCPP_AUTO_CAST(__t.end()) } -> sentinel_for<iterator_t<_Tp>>;
111fe6060f1SDimitry Andric     };
112fe6060f1SDimitry Andric 
113fe6060f1SDimitry Andric   void end(auto&) = delete;
114fe6060f1SDimitry Andric   void end(const auto&) = delete;
115fe6060f1SDimitry Andric 
116fe6060f1SDimitry Andric   template <class _Tp>
117fe6060f1SDimitry Andric   concept __unqualified_end =
118fe6060f1SDimitry Andric     !__member_end<_Tp> &&
119fe6060f1SDimitry Andric     __can_borrow<_Tp> &&
120fe6060f1SDimitry Andric     __class_or_enum<remove_cvref_t<_Tp>> &&
121fe6060f1SDimitry Andric     requires(_Tp && __t) {
122fe6060f1SDimitry Andric       typename iterator_t<_Tp>;
1230eae32dcSDimitry Andric       { _LIBCPP_AUTO_CAST(end(__t)) } -> sentinel_for<iterator_t<_Tp>>;
124fe6060f1SDimitry Andric     };
125fe6060f1SDimitry Andric 
126fe6060f1SDimitry Andric   class __fn {
127fe6060f1SDimitry Andric   public:
128fe6060f1SDimitry Andric     template <class _Tp, size_t _Np>
1290eae32dcSDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept
1300eae32dcSDimitry Andric       requires (sizeof(*__t) != 0)  // Disallow incomplete element types.
1310eae32dcSDimitry Andric     {
132fe6060f1SDimitry Andric       return __t + _Np;
133fe6060f1SDimitry Andric     }
134fe6060f1SDimitry Andric 
135fe6060f1SDimitry Andric     template <class _Tp>
136fe6060f1SDimitry Andric       requires __member_end<_Tp>
137fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
1380eae32dcSDimitry Andric       noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.end())))
139fe6060f1SDimitry Andric     {
1400eae32dcSDimitry Andric       return _LIBCPP_AUTO_CAST(__t.end());
141fe6060f1SDimitry Andric     }
142fe6060f1SDimitry Andric 
143fe6060f1SDimitry Andric     template <class _Tp>
144fe6060f1SDimitry Andric       requires __unqualified_end<_Tp>
145fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
1460eae32dcSDimitry Andric       noexcept(noexcept(_LIBCPP_AUTO_CAST(end(__t))))
147fe6060f1SDimitry Andric     {
1480eae32dcSDimitry Andric       return _LIBCPP_AUTO_CAST(end(__t));
149fe6060f1SDimitry Andric     }
150fe6060f1SDimitry Andric 
151fe6060f1SDimitry Andric     void operator()(auto&&) const = delete;
152fe6060f1SDimitry Andric   };
1530eae32dcSDimitry Andric }
154fe6060f1SDimitry Andric 
1550eae32dcSDimitry Andric inline namespace __cpo {
156fe6060f1SDimitry Andric   inline constexpr auto end = __end::__fn{};
1570eae32dcSDimitry Andric } // namespace __cpo
1580eae32dcSDimitry Andric } // namespace ranges
159fe6060f1SDimitry Andric 
1600eae32dcSDimitry Andric // [range.access.cbegin]
1610eae32dcSDimitry Andric 
1620eae32dcSDimitry Andric namespace ranges {
1630eae32dcSDimitry Andric namespace __cbegin {
164fe6060f1SDimitry Andric   struct __fn {
165fe6060f1SDimitry Andric     template <class _Tp>
166*04eeddc0SDimitry Andric       requires is_lvalue_reference_v<_Tp&&>
167*04eeddc0SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
168*04eeddc0SDimitry Andric     constexpr auto operator()(_Tp&& __t) const
169*04eeddc0SDimitry Andric       noexcept(noexcept(ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t))))
170*04eeddc0SDimitry Andric       -> decltype(      ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t)))
171*04eeddc0SDimitry Andric       { return          ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t)); }
172fe6060f1SDimitry Andric 
173fe6060f1SDimitry Andric     template <class _Tp>
174*04eeddc0SDimitry Andric       requires is_rvalue_reference_v<_Tp&&>
175*04eeddc0SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
176*04eeddc0SDimitry Andric     constexpr auto operator()(_Tp&& __t) const
177*04eeddc0SDimitry Andric       noexcept(noexcept(ranges::begin(static_cast<const _Tp&&>(__t))))
178*04eeddc0SDimitry Andric       -> decltype(      ranges::begin(static_cast<const _Tp&&>(__t)))
179*04eeddc0SDimitry Andric       { return          ranges::begin(static_cast<const _Tp&&>(__t)); }
180fe6060f1SDimitry Andric   };
1810eae32dcSDimitry Andric }
182fe6060f1SDimitry Andric 
1830eae32dcSDimitry Andric inline namespace __cpo {
184fe6060f1SDimitry Andric   inline constexpr auto cbegin = __cbegin::__fn{};
1850eae32dcSDimitry Andric } // namespace __cpo
1860eae32dcSDimitry Andric } // namespace ranges
187fe6060f1SDimitry Andric 
1880eae32dcSDimitry Andric // [range.access.cend]
1890eae32dcSDimitry Andric 
1900eae32dcSDimitry Andric namespace ranges {
1910eae32dcSDimitry Andric namespace __cend {
192fe6060f1SDimitry Andric   struct __fn {
193fe6060f1SDimitry Andric     template <class _Tp>
194*04eeddc0SDimitry Andric       requires is_lvalue_reference_v<_Tp&&>
195*04eeddc0SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
196*04eeddc0SDimitry Andric     constexpr auto operator()(_Tp&& __t) const
197*04eeddc0SDimitry Andric       noexcept(noexcept(ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t))))
198*04eeddc0SDimitry Andric       -> decltype(      ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t)))
199*04eeddc0SDimitry Andric       { return          ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t)); }
200fe6060f1SDimitry Andric 
201fe6060f1SDimitry Andric     template <class _Tp>
202*04eeddc0SDimitry Andric       requires is_rvalue_reference_v<_Tp&&>
203*04eeddc0SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
204*04eeddc0SDimitry Andric     constexpr auto operator()(_Tp&& __t) const
205*04eeddc0SDimitry Andric       noexcept(noexcept(ranges::end(static_cast<const _Tp&&>(__t))))
206*04eeddc0SDimitry Andric       -> decltype(      ranges::end(static_cast<const _Tp&&>(__t)))
207*04eeddc0SDimitry Andric       { return          ranges::end(static_cast<const _Tp&&>(__t)); }
208fe6060f1SDimitry Andric   };
2090eae32dcSDimitry Andric }
210fe6060f1SDimitry Andric 
2110eae32dcSDimitry Andric inline namespace __cpo {
212fe6060f1SDimitry Andric   inline constexpr auto cend = __cend::__fn{};
2130eae32dcSDimitry Andric } // namespace __cpo
2140eae32dcSDimitry Andric } // namespace ranges
215fe6060f1SDimitry Andric 
216fe6060f1SDimitry Andric #endif // !defined(_LIBCPP_HAS_NO_RANGES)
217fe6060f1SDimitry Andric 
218fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
219fe6060f1SDimitry Andric 
220fe6060f1SDimitry Andric #endif // _LIBCPP___RANGES_ACCESS_H
221