xref: /freebsd/contrib/llvm-project/libcxx/include/__ranges/access.h (revision fe6060f10f634930ff71b7c50291ddc610da2475)
1*fe6060f1SDimitry Andric // -*- C++ -*-
2*fe6060f1SDimitry Andric //===------------------------ __ranges/access.h ---------------------------===//
3*fe6060f1SDimitry Andric //
4*fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6*fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*fe6060f1SDimitry Andric //
8*fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
9*fe6060f1SDimitry Andric #ifndef _LIBCPP___RANGES_ACCESS_H
10*fe6060f1SDimitry Andric #define _LIBCPP___RANGES_ACCESS_H
11*fe6060f1SDimitry Andric 
12*fe6060f1SDimitry Andric #include <__config>
13*fe6060f1SDimitry Andric #include <__iterator/concepts.h>
14*fe6060f1SDimitry Andric #include <__iterator/readable_traits.h>
15*fe6060f1SDimitry Andric #include <__ranges/enable_borrowed_range.h>
16*fe6060f1SDimitry Andric #include <__utility/__decay_copy.h>
17*fe6060f1SDimitry Andric #include <__utility/forward.h>
18*fe6060f1SDimitry Andric #include <concepts>
19*fe6060f1SDimitry Andric #include <type_traits>
20*fe6060f1SDimitry Andric 
21*fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22*fe6060f1SDimitry Andric #pragma GCC system_header
23*fe6060f1SDimitry Andric #endif
24*fe6060f1SDimitry Andric 
25*fe6060f1SDimitry Andric _LIBCPP_PUSH_MACROS
26*fe6060f1SDimitry Andric #include <__undef_macros>
27*fe6060f1SDimitry Andric 
28*fe6060f1SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
29*fe6060f1SDimitry Andric 
30*fe6060f1SDimitry Andric #if !defined(_LIBCPP_HAS_NO_RANGES)
31*fe6060f1SDimitry Andric 
32*fe6060f1SDimitry Andric // clang-format off
33*fe6060f1SDimitry Andric 
34*fe6060f1SDimitry Andric namespace ranges {
35*fe6060f1SDimitry Andric   template <class _Tp>
36*fe6060f1SDimitry Andric   concept __can_borrow =
37*fe6060f1SDimitry Andric       is_lvalue_reference_v<_Tp> || enable_borrowed_range<remove_cvref_t<_Tp> >;
38*fe6060f1SDimitry Andric 
39*fe6060f1SDimitry Andric   template<class _Tp>
40*fe6060f1SDimitry Andric   concept __is_complete = requires { sizeof(_Tp); };
41*fe6060f1SDimitry Andric } // namespace ranges
42*fe6060f1SDimitry Andric 
43*fe6060f1SDimitry Andric // [range.access.begin]
44*fe6060f1SDimitry Andric namespace ranges::__begin {
45*fe6060f1SDimitry Andric   template <class _Tp>
46*fe6060f1SDimitry Andric   concept __member_begin =
47*fe6060f1SDimitry Andric     __can_borrow<_Tp> &&
48*fe6060f1SDimitry Andric     requires(_Tp&& __t) {
49*fe6060f1SDimitry Andric       { _VSTD::__decay_copy(__t.begin()) } -> input_or_output_iterator;
50*fe6060f1SDimitry Andric     };
51*fe6060f1SDimitry Andric 
52*fe6060f1SDimitry Andric   void begin(auto&) = delete;
53*fe6060f1SDimitry Andric   void begin(const auto&) = delete;
54*fe6060f1SDimitry Andric 
55*fe6060f1SDimitry Andric   template <class _Tp>
56*fe6060f1SDimitry Andric   concept __unqualified_begin =
57*fe6060f1SDimitry Andric     !__member_begin<_Tp> &&
58*fe6060f1SDimitry Andric     __can_borrow<_Tp> &&
59*fe6060f1SDimitry Andric     __class_or_enum<remove_cvref_t<_Tp> > &&
60*fe6060f1SDimitry Andric     requires(_Tp && __t) {
61*fe6060f1SDimitry Andric       { _VSTD::__decay_copy(begin(__t)) } -> input_or_output_iterator;
62*fe6060f1SDimitry Andric     };
63*fe6060f1SDimitry Andric 
64*fe6060f1SDimitry Andric   struct __fn {
65*fe6060f1SDimitry Andric     template <class _Tp>
66*fe6060f1SDimitry Andric     requires is_array_v<remove_cv_t<_Tp>>
67*fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __t) const noexcept {
68*fe6060f1SDimitry Andric       constexpr bool __complete = __is_complete<iter_value_t<_Tp> >;
69*fe6060f1SDimitry Andric       if constexpr (__complete) { // used to disable cryptic diagnostic
70*fe6060f1SDimitry Andric         return __t + 0;
71*fe6060f1SDimitry Andric       }
72*fe6060f1SDimitry Andric       else {
73*fe6060f1SDimitry Andric         static_assert(__complete, "`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type.");
74*fe6060f1SDimitry Andric       }
75*fe6060f1SDimitry Andric     }
76*fe6060f1SDimitry Andric 
77*fe6060f1SDimitry Andric     template <class _Tp>
78*fe6060f1SDimitry Andric     requires __member_begin<_Tp>
79*fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
80*fe6060f1SDimitry Andric     noexcept(noexcept(_VSTD::__decay_copy(__t.begin())))
81*fe6060f1SDimitry Andric     {
82*fe6060f1SDimitry Andric       return __t.begin();
83*fe6060f1SDimitry Andric     }
84*fe6060f1SDimitry Andric 
85*fe6060f1SDimitry Andric     template <class _Tp>
86*fe6060f1SDimitry Andric     requires __unqualified_begin<_Tp>
87*fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
88*fe6060f1SDimitry Andric     noexcept(noexcept(_VSTD::__decay_copy(begin(__t))))
89*fe6060f1SDimitry Andric     {
90*fe6060f1SDimitry Andric       return begin(__t);
91*fe6060f1SDimitry Andric     }
92*fe6060f1SDimitry Andric 
93*fe6060f1SDimitry Andric     void operator()(auto&&) const = delete;
94*fe6060f1SDimitry Andric   };
95*fe6060f1SDimitry Andric } // namespace ranges::__begin
96*fe6060f1SDimitry Andric 
97*fe6060f1SDimitry Andric namespace ranges {
98*fe6060f1SDimitry Andric   inline namespace __cpo {
99*fe6060f1SDimitry Andric     inline constexpr auto begin = __begin::__fn{};
100*fe6060f1SDimitry Andric   } // namespace __cpo
101*fe6060f1SDimitry Andric 
102*fe6060f1SDimitry Andric   template <class _Tp>
103*fe6060f1SDimitry Andric   using iterator_t = decltype(ranges::begin(declval<_Tp&>()));
104*fe6060f1SDimitry Andric } // namespace ranges
105*fe6060f1SDimitry Andric 
106*fe6060f1SDimitry Andric // [range.access.end]
107*fe6060f1SDimitry Andric namespace ranges::__end {
108*fe6060f1SDimitry Andric   template <class _Tp>
109*fe6060f1SDimitry Andric   concept __member_end =
110*fe6060f1SDimitry Andric     __can_borrow<_Tp> &&
111*fe6060f1SDimitry Andric     requires(_Tp&& __t) {
112*fe6060f1SDimitry Andric       typename iterator_t<_Tp>;
113*fe6060f1SDimitry Andric       { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).end()) } -> sentinel_for<iterator_t<_Tp> >;
114*fe6060f1SDimitry Andric     };
115*fe6060f1SDimitry Andric 
116*fe6060f1SDimitry Andric   void end(auto&) = delete;
117*fe6060f1SDimitry Andric   void end(const auto&) = delete;
118*fe6060f1SDimitry Andric 
119*fe6060f1SDimitry Andric   template <class _Tp>
120*fe6060f1SDimitry Andric   concept __unqualified_end =
121*fe6060f1SDimitry Andric     !__member_end<_Tp> &&
122*fe6060f1SDimitry Andric     __can_borrow<_Tp> &&
123*fe6060f1SDimitry Andric     __class_or_enum<remove_cvref_t<_Tp> > &&
124*fe6060f1SDimitry Andric     requires(_Tp && __t) {
125*fe6060f1SDimitry Andric       typename iterator_t<_Tp>;
126*fe6060f1SDimitry Andric       { _VSTD::__decay_copy(end(_VSTD::forward<_Tp>(__t))) } -> sentinel_for<iterator_t<_Tp> >;
127*fe6060f1SDimitry Andric     };
128*fe6060f1SDimitry Andric 
129*fe6060f1SDimitry Andric   class __fn {
130*fe6060f1SDimitry Andric   public:
131*fe6060f1SDimitry Andric     template <class _Tp, size_t _Np>
132*fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept {
133*fe6060f1SDimitry Andric       constexpr bool __complete = __is_complete<remove_cv_t<_Tp> >;
134*fe6060f1SDimitry Andric       if constexpr (__complete) { // used to disable cryptic diagnostic
135*fe6060f1SDimitry Andric         return __t + _Np;
136*fe6060f1SDimitry Andric       }
137*fe6060f1SDimitry Andric       else {
138*fe6060f1SDimitry Andric         static_assert(__complete, "`std::ranges::end` is SFINAE-unfriendly on arrays of an incomplete type.");
139*fe6060f1SDimitry Andric       }
140*fe6060f1SDimitry Andric     }
141*fe6060f1SDimitry Andric 
142*fe6060f1SDimitry Andric     template <class _Tp>
143*fe6060f1SDimitry Andric     requires __member_end<_Tp>
144*fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
145*fe6060f1SDimitry Andric     noexcept(noexcept(_VSTD::__decay_copy(__t.end())))
146*fe6060f1SDimitry Andric     {
147*fe6060f1SDimitry Andric       return _VSTD::forward<_Tp>(__t).end();
148*fe6060f1SDimitry Andric     }
149*fe6060f1SDimitry Andric 
150*fe6060f1SDimitry Andric     template <class _Tp>
151*fe6060f1SDimitry Andric     requires __unqualified_end<_Tp>
152*fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
153*fe6060f1SDimitry Andric     noexcept(noexcept(_VSTD::__decay_copy(end(__t))))
154*fe6060f1SDimitry Andric     {
155*fe6060f1SDimitry Andric       return end(__t);
156*fe6060f1SDimitry Andric     }
157*fe6060f1SDimitry Andric 
158*fe6060f1SDimitry Andric     void operator()(auto&&) const = delete;
159*fe6060f1SDimitry Andric   };
160*fe6060f1SDimitry Andric } // namespace ranges::__end
161*fe6060f1SDimitry Andric 
162*fe6060f1SDimitry Andric namespace ranges::inline __cpo {
163*fe6060f1SDimitry Andric   inline constexpr auto end = __end::__fn{};
164*fe6060f1SDimitry Andric } // namespace ranges::__cpo
165*fe6060f1SDimitry Andric 
166*fe6060f1SDimitry Andric namespace ranges::__cbegin {
167*fe6060f1SDimitry Andric   struct __fn {
168*fe6060f1SDimitry Andric     template <class _Tp>
169*fe6060f1SDimitry Andric     requires invocable<decltype(ranges::begin), _Tp const&>
170*fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __t) const
171*fe6060f1SDimitry Andric     noexcept(noexcept(ranges::begin(_VSTD::as_const(__t))))
172*fe6060f1SDimitry Andric     {
173*fe6060f1SDimitry Andric       return ranges::begin(_VSTD::as_const(__t));
174*fe6060f1SDimitry Andric     }
175*fe6060f1SDimitry Andric 
176*fe6060f1SDimitry Andric     template <class _Tp>
177*fe6060f1SDimitry Andric     requires is_rvalue_reference_v<_Tp> && invocable<decltype(ranges::begin), _Tp const&&>
178*fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
179*fe6060f1SDimitry Andric     noexcept(noexcept(ranges::begin(static_cast<_Tp const&&>(__t))))
180*fe6060f1SDimitry Andric     {
181*fe6060f1SDimitry Andric       return ranges::begin(static_cast<_Tp const&&>(__t));
182*fe6060f1SDimitry Andric     }
183*fe6060f1SDimitry Andric   };
184*fe6060f1SDimitry Andric } // namespace ranges::__cbegin
185*fe6060f1SDimitry Andric 
186*fe6060f1SDimitry Andric namespace ranges::inline __cpo {
187*fe6060f1SDimitry Andric   inline constexpr auto cbegin = __cbegin::__fn{};
188*fe6060f1SDimitry Andric } // namespace ranges::__cpo
189*fe6060f1SDimitry Andric 
190*fe6060f1SDimitry Andric namespace ranges::__cend {
191*fe6060f1SDimitry Andric   struct __fn {
192*fe6060f1SDimitry Andric     template <class _Tp>
193*fe6060f1SDimitry Andric     requires invocable<decltype(ranges::end), _Tp const&>
194*fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __t) const
195*fe6060f1SDimitry Andric     noexcept(noexcept(ranges::end(_VSTD::as_const(__t))))
196*fe6060f1SDimitry Andric     {
197*fe6060f1SDimitry Andric       return ranges::end(_VSTD::as_const(__t));
198*fe6060f1SDimitry Andric     }
199*fe6060f1SDimitry Andric 
200*fe6060f1SDimitry Andric     template <class _Tp>
201*fe6060f1SDimitry Andric     requires is_rvalue_reference_v<_Tp> && invocable<decltype(ranges::end), _Tp const&&>
202*fe6060f1SDimitry Andric     [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
203*fe6060f1SDimitry Andric     noexcept(noexcept(ranges::end(static_cast<_Tp const&&>(__t))))
204*fe6060f1SDimitry Andric     {
205*fe6060f1SDimitry Andric       return ranges::end(static_cast<_Tp const&&>(__t));
206*fe6060f1SDimitry Andric     }
207*fe6060f1SDimitry Andric   };
208*fe6060f1SDimitry Andric } // namespace ranges::__cend
209*fe6060f1SDimitry Andric 
210*fe6060f1SDimitry Andric namespace ranges::inline __cpo {
211*fe6060f1SDimitry Andric   inline constexpr auto cend = __cend::__fn{};
212*fe6060f1SDimitry Andric } // namespace ranges::__cpo
213*fe6060f1SDimitry Andric 
214*fe6060f1SDimitry Andric // clang-format off
215*fe6060f1SDimitry Andric 
216*fe6060f1SDimitry Andric #endif // !defined(_LIBCPP_HAS_NO_RANGES)
217*fe6060f1SDimitry Andric 
218*fe6060f1SDimitry Andric _LIBCPP_END_NAMESPACE_STD
219*fe6060f1SDimitry Andric 
220*fe6060f1SDimitry Andric _LIBCPP_POP_MACROS
221*fe6060f1SDimitry Andric 
222*fe6060f1SDimitry Andric #endif // _LIBCPP___RANGES_ACCESS_H
223