xref: /freebsd-src/contrib/llvm-project/libcxx/include/__ranges/access.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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 
1204eeddc0SDimitry 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>
170eae32dcSDimitry Andric #include <__utility/auto_cast.h>
18fe6060f1SDimitry Andric #include <type_traits>
19fe6060f1SDimitry Andric 
20fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
21fe6060f1SDimitry Andric #  pragma GCC system_header
22fe6060f1SDimitry Andric #endif
23fe6060f1SDimitry Andric 
24fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
25fe6060f1SDimitry Andric 
26*81ad6265SDimitry Andric #if _LIBCPP_STD_VER > 17
27fe6060f1SDimitry Andric 
28fe6060f1SDimitry Andric namespace ranges {
29fe6060f1SDimitry Andric   template <class _Tp>
30fe6060f1SDimitry Andric   concept __can_borrow =
31fe6060f1SDimitry Andric     is_lvalue_reference_v<_Tp> || enable_borrowed_range<remove_cvref_t<_Tp>>;
32fe6060f1SDimitry Andric } // namespace ranges
33fe6060f1SDimitry Andric 
34fe6060f1SDimitry Andric // [range.access.begin]
350eae32dcSDimitry Andric 
360eae32dcSDimitry Andric namespace ranges {
370eae32dcSDimitry Andric namespace __begin {
38fe6060f1SDimitry Andric   template <class _Tp>
39fe6060f1SDimitry Andric   concept __member_begin =
40fe6060f1SDimitry Andric     __can_borrow<_Tp> &&
4104eeddc0SDimitry Andric     __workaround_52970<_Tp> &&
42fe6060f1SDimitry Andric     requires(_Tp&& __t) {
430eae32dcSDimitry Andric       { _LIBCPP_AUTO_CAST(__t.begin()) } -> input_or_output_iterator;
44fe6060f1SDimitry Andric     };
45fe6060f1SDimitry Andric 
46fe6060f1SDimitry Andric   void begin(auto&) = delete;
47fe6060f1SDimitry Andric   void begin(const auto&) = delete;
48fe6060f1SDimitry Andric 
49fe6060f1SDimitry Andric   template <class _Tp>
50fe6060f1SDimitry Andric   concept __unqualified_begin =
51fe6060f1SDimitry Andric     !__member_begin<_Tp> &&
52fe6060f1SDimitry Andric     __can_borrow<_Tp> &&
53fe6060f1SDimitry Andric     __class_or_enum<remove_cvref_t<_Tp>> &&
54fe6060f1SDimitry Andric     requires(_Tp && __t) {
550eae32dcSDimitry Andric       { _LIBCPP_AUTO_CAST(begin(__t)) } -> input_or_output_iterator;
56fe6060f1SDimitry Andric     };
57fe6060f1SDimitry Andric 
58fe6060f1SDimitry Andric   struct __fn {
59fe6060f1SDimitry Andric     template <class _Tp>
601838bd0fSDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[]) const noexcept
61*81ad6265SDimitry Andric       requires (sizeof(_Tp) >= 0)  // Disallow incomplete element types.
620eae32dcSDimitry Andric     {
631838bd0fSDimitry Andric       return __t + 0;
641838bd0fSDimitry Andric     }
651838bd0fSDimitry Andric 
661838bd0fSDimitry Andric     template <class _Tp, size_t _Np>
671838bd0fSDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept
68*81ad6265SDimitry Andric       requires (sizeof(_Tp) >= 0)  // Disallow incomplete element types.
691838bd0fSDimitry Andric     {
701838bd0fSDimitry Andric       return __t + 0;
71fe6060f1SDimitry Andric     }
72fe6060f1SDimitry Andric 
73fe6060f1SDimitry Andric     template <class _Tp>
74fe6060f1SDimitry Andric       requires __member_begin<_Tp>
75fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
760eae32dcSDimitry Andric       noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.begin())))
77fe6060f1SDimitry Andric     {
780eae32dcSDimitry Andric       return _LIBCPP_AUTO_CAST(__t.begin());
79fe6060f1SDimitry Andric     }
80fe6060f1SDimitry Andric 
81fe6060f1SDimitry Andric     template <class _Tp>
82fe6060f1SDimitry Andric       requires __unqualified_begin<_Tp>
83fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
840eae32dcSDimitry Andric       noexcept(noexcept(_LIBCPP_AUTO_CAST(begin(__t))))
85fe6060f1SDimitry Andric     {
860eae32dcSDimitry Andric       return _LIBCPP_AUTO_CAST(begin(__t));
87fe6060f1SDimitry Andric     }
88fe6060f1SDimitry Andric 
89fe6060f1SDimitry Andric     void operator()(auto&&) const = delete;
90fe6060f1SDimitry Andric   };
911fd87a68SDimitry Andric } // namespace __begin
92fe6060f1SDimitry Andric 
93fe6060f1SDimitry Andric inline namespace __cpo {
94fe6060f1SDimitry Andric   inline constexpr auto begin = __begin::__fn{};
95fe6060f1SDimitry Andric } // namespace __cpo
960eae32dcSDimitry Andric } // namespace ranges
97fe6060f1SDimitry Andric 
980eae32dcSDimitry Andric // [range.range]
990eae32dcSDimitry Andric 
1000eae32dcSDimitry Andric namespace ranges {
101fe6060f1SDimitry Andric   template <class _Tp>
102fe6060f1SDimitry Andric   using iterator_t = decltype(ranges::begin(declval<_Tp&>()));
103fe6060f1SDimitry Andric } // namespace ranges
104fe6060f1SDimitry Andric 
105fe6060f1SDimitry Andric // [range.access.end]
1060eae32dcSDimitry Andric 
1070eae32dcSDimitry Andric namespace ranges {
1080eae32dcSDimitry Andric namespace __end {
109fe6060f1SDimitry Andric   template <class _Tp>
110fe6060f1SDimitry Andric   concept __member_end =
111fe6060f1SDimitry Andric     __can_borrow<_Tp> &&
11204eeddc0SDimitry Andric     __workaround_52970<_Tp> &&
113fe6060f1SDimitry Andric     requires(_Tp&& __t) {
114fe6060f1SDimitry Andric       typename iterator_t<_Tp>;
1150eae32dcSDimitry Andric       { _LIBCPP_AUTO_CAST(__t.end()) } -> sentinel_for<iterator_t<_Tp>>;
116fe6060f1SDimitry Andric     };
117fe6060f1SDimitry Andric 
118fe6060f1SDimitry Andric   void end(auto&) = delete;
119fe6060f1SDimitry Andric   void end(const auto&) = delete;
120fe6060f1SDimitry Andric 
121fe6060f1SDimitry Andric   template <class _Tp>
122fe6060f1SDimitry Andric   concept __unqualified_end =
123fe6060f1SDimitry Andric     !__member_end<_Tp> &&
124fe6060f1SDimitry Andric     __can_borrow<_Tp> &&
125fe6060f1SDimitry Andric     __class_or_enum<remove_cvref_t<_Tp>> &&
126fe6060f1SDimitry Andric     requires(_Tp && __t) {
127fe6060f1SDimitry Andric       typename iterator_t<_Tp>;
1280eae32dcSDimitry Andric       { _LIBCPP_AUTO_CAST(end(__t)) } -> sentinel_for<iterator_t<_Tp>>;
129fe6060f1SDimitry Andric     };
130fe6060f1SDimitry Andric 
131*81ad6265SDimitry Andric   struct __fn {
132fe6060f1SDimitry Andric     template <class _Tp, size_t _Np>
1330eae32dcSDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept
134*81ad6265SDimitry Andric       requires (sizeof(_Tp) >= 0)  // Disallow incomplete element types.
1350eae32dcSDimitry Andric     {
136fe6060f1SDimitry Andric       return __t + _Np;
137fe6060f1SDimitry Andric     }
138fe6060f1SDimitry Andric 
139fe6060f1SDimitry Andric     template <class _Tp>
140fe6060f1SDimitry Andric       requires __member_end<_Tp>
141fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
1420eae32dcSDimitry Andric       noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.end())))
143fe6060f1SDimitry Andric     {
1440eae32dcSDimitry Andric       return _LIBCPP_AUTO_CAST(__t.end());
145fe6060f1SDimitry Andric     }
146fe6060f1SDimitry Andric 
147fe6060f1SDimitry Andric     template <class _Tp>
148fe6060f1SDimitry Andric       requires __unqualified_end<_Tp>
149fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
1500eae32dcSDimitry Andric       noexcept(noexcept(_LIBCPP_AUTO_CAST(end(__t))))
151fe6060f1SDimitry Andric     {
1520eae32dcSDimitry Andric       return _LIBCPP_AUTO_CAST(end(__t));
153fe6060f1SDimitry Andric     }
154fe6060f1SDimitry Andric 
155fe6060f1SDimitry Andric     void operator()(auto&&) const = delete;
156fe6060f1SDimitry Andric   };
1571fd87a68SDimitry Andric } // namespace __end
158fe6060f1SDimitry Andric 
1590eae32dcSDimitry Andric inline namespace __cpo {
160fe6060f1SDimitry Andric   inline constexpr auto end = __end::__fn{};
1610eae32dcSDimitry Andric } // namespace __cpo
1620eae32dcSDimitry Andric } // namespace ranges
163fe6060f1SDimitry Andric 
1640eae32dcSDimitry Andric // [range.access.cbegin]
1650eae32dcSDimitry Andric 
1660eae32dcSDimitry Andric namespace ranges {
1670eae32dcSDimitry Andric namespace __cbegin {
168fe6060f1SDimitry Andric   struct __fn {
169fe6060f1SDimitry Andric     template <class _Tp>
17004eeddc0SDimitry Andric       requires is_lvalue_reference_v<_Tp&&>
17104eeddc0SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
17204eeddc0SDimitry Andric     constexpr auto operator()(_Tp&& __t) const
17304eeddc0SDimitry Andric       noexcept(noexcept(ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t))))
17404eeddc0SDimitry Andric       -> decltype(      ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t)))
17504eeddc0SDimitry Andric       { return          ranges::begin(static_cast<const remove_reference_t<_Tp>&>(__t)); }
176fe6060f1SDimitry Andric 
177fe6060f1SDimitry Andric     template <class _Tp>
17804eeddc0SDimitry Andric       requires is_rvalue_reference_v<_Tp&&>
17904eeddc0SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
18004eeddc0SDimitry Andric     constexpr auto operator()(_Tp&& __t) const
18104eeddc0SDimitry Andric       noexcept(noexcept(ranges::begin(static_cast<const _Tp&&>(__t))))
18204eeddc0SDimitry Andric       -> decltype(      ranges::begin(static_cast<const _Tp&&>(__t)))
18304eeddc0SDimitry Andric       { return          ranges::begin(static_cast<const _Tp&&>(__t)); }
184fe6060f1SDimitry Andric   };
1851fd87a68SDimitry Andric } // namespace __cbegin
186fe6060f1SDimitry Andric 
1870eae32dcSDimitry Andric inline namespace __cpo {
188fe6060f1SDimitry Andric   inline constexpr auto cbegin = __cbegin::__fn{};
1890eae32dcSDimitry Andric } // namespace __cpo
1900eae32dcSDimitry Andric } // namespace ranges
191fe6060f1SDimitry Andric 
1920eae32dcSDimitry Andric // [range.access.cend]
1930eae32dcSDimitry Andric 
1940eae32dcSDimitry Andric namespace ranges {
1950eae32dcSDimitry Andric namespace __cend {
196fe6060f1SDimitry Andric   struct __fn {
197fe6060f1SDimitry Andric     template <class _Tp>
19804eeddc0SDimitry Andric       requires is_lvalue_reference_v<_Tp&&>
19904eeddc0SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
20004eeddc0SDimitry Andric     constexpr auto operator()(_Tp&& __t) const
20104eeddc0SDimitry Andric       noexcept(noexcept(ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t))))
20204eeddc0SDimitry Andric       -> decltype(      ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t)))
20304eeddc0SDimitry Andric       { return          ranges::end(static_cast<const remove_reference_t<_Tp>&>(__t)); }
204fe6060f1SDimitry Andric 
205fe6060f1SDimitry Andric     template <class _Tp>
20604eeddc0SDimitry Andric       requires is_rvalue_reference_v<_Tp&&>
20704eeddc0SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI
20804eeddc0SDimitry Andric     constexpr auto operator()(_Tp&& __t) const
20904eeddc0SDimitry Andric       noexcept(noexcept(ranges::end(static_cast<const _Tp&&>(__t))))
21004eeddc0SDimitry Andric       -> decltype(      ranges::end(static_cast<const _Tp&&>(__t)))
21104eeddc0SDimitry Andric       { return          ranges::end(static_cast<const _Tp&&>(__t)); }
212fe6060f1SDimitry Andric   };
2131fd87a68SDimitry Andric } // namespace __cend
214fe6060f1SDimitry Andric 
2150eae32dcSDimitry Andric inline namespace __cpo {
216fe6060f1SDimitry Andric   inline constexpr auto cend = __cend::__fn{};
2170eae32dcSDimitry Andric } // namespace __cpo
2180eae32dcSDimitry Andric } // namespace ranges
219fe6060f1SDimitry Andric 
220*81ad6265SDimitry Andric #endif // _LIBCPP_STD_VER > 17
221fe6060f1SDimitry Andric 
222fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
223fe6060f1SDimitry Andric 
224fe6060f1SDimitry Andric #endif // _LIBCPP___RANGES_ACCESS_H
225