2 //===----------------------------------------------------------------------===//
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___RANGES_ACCESS_H
11 #define _LIBCPP___RANGES_ACCESS_H
13 #include <__concepts/class_or_enum.h>
15 #include <__iterator/concepts.h>
16 #include <__iterator/readable_traits.h>
17 #include <__ranges/enable_borrowed_range.h>
18 #include <__type_traits/decay.h>
19 #include <__type_traits/is_reference.h>
20 #include <__type_traits/remove_cvref.h>
21 #include <__type_traits/remove_reference.h>
22 #include <__utility/auto_cast.h>
23 #include <__utility/declval.h>
26 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
27 # pragma GCC system_header
30 _LIBCPP_BEGIN_NAMESPACE_STD
32 #if _LIBCPP_STD_VER >= 20
36 concept __can_borrow
=
37 is_lvalue_reference_v
<_Tp
> || enable_borrowed_range
<remove_cvref_t
<_Tp
>>;
40 // [range.access.begin]
45 concept __member_begin
=
47 __workaround_52970
<_Tp
> &&
49 { _LIBCPP_AUTO_CAST(__t
.begin()) } -> input_or_output_iterator
;
52 void begin(auto&) = delete;
53 void begin(const auto&) = delete;
56 concept __unqualified_begin
=
57 !__member_begin
<_Tp
> &&
59 __class_or_enum
<remove_cvref_t
<_Tp
>> &&
60 requires(_Tp
&& __t
) {
61 { _LIBCPP_AUTO_CAST(begin(__t
)) } -> input_or_output_iterator
;
66 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Tp (&__t
)[]) const noexcept
67 requires (sizeof(_Tp
) >= 0) // Disallow incomplete element types.
72 template <class _Tp
, size_t _Np
>
73 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Tp (&__t
)[_Np
]) const noexcept
74 requires (sizeof(_Tp
) >= 0) // Disallow incomplete element types.
80 requires __member_begin
<_Tp
>
81 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Tp
&& __t
) const
82 noexcept(noexcept(_LIBCPP_AUTO_CAST(__t
.begin())))
84 return _LIBCPP_AUTO_CAST(__t
.begin());
88 requires __unqualified_begin
<_Tp
>
89 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Tp
&& __t
) const
90 noexcept(noexcept(_LIBCPP_AUTO_CAST(begin(__t
))))
92 return _LIBCPP_AUTO_CAST(begin(__t
));
95 void operator()(auto&&) const = delete;
97 } // namespace __begin
99 inline namespace __cpo
{
100 inline constexpr auto begin
= __begin::__fn
{};
102 } // namespace ranges
108 using iterator_t
= decltype(ranges::begin(std::declval
<_Tp
&>()));
109 } // namespace ranges
111 // [range.access.end]
116 concept __member_end
=
118 __workaround_52970
<_Tp
> &&
119 requires(_Tp
&& __t
) {
120 typename iterator_t
<_Tp
>;
121 { _LIBCPP_AUTO_CAST(__t
.end()) } -> sentinel_for
<iterator_t
<_Tp
>>;
124 void end(auto&) = delete;
125 void end(const auto&) = delete;
128 concept __unqualified_end
=
129 !__member_end
<_Tp
> &&
131 __class_or_enum
<remove_cvref_t
<_Tp
>> &&
132 requires(_Tp
&& __t
) {
133 typename iterator_t
<_Tp
>;
134 { _LIBCPP_AUTO_CAST(end(__t
)) } -> sentinel_for
<iterator_t
<_Tp
>>;
138 template <class _Tp
, size_t _Np
>
139 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Tp (&__t
)[_Np
]) const noexcept
140 requires (sizeof(_Tp
) >= 0) // Disallow incomplete element types.
146 requires __member_end
<_Tp
>
147 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Tp
&& __t
) const
148 noexcept(noexcept(_LIBCPP_AUTO_CAST(__t
.end())))
150 return _LIBCPP_AUTO_CAST(__t
.end());
154 requires __unqualified_end
<_Tp
>
155 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
constexpr auto operator()(_Tp
&& __t
) const
156 noexcept(noexcept(_LIBCPP_AUTO_CAST(end(__t
))))
158 return _LIBCPP_AUTO_CAST(end(__t
));
161 void operator()(auto&&) const = delete;
165 inline namespace __cpo
{
166 inline constexpr auto end
= __end::__fn
{};
168 } // namespace ranges
170 // [range.access.cbegin]
176 requires is_lvalue_reference_v
<_Tp
&&>
177 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
178 constexpr auto operator()(_Tp
&& __t
) const
179 noexcept(noexcept(ranges::begin(static_cast<const remove_reference_t
<_Tp
>&>(__t
))))
180 -> decltype( ranges::begin(static_cast<const remove_reference_t
<_Tp
>&>(__t
)))
181 { return ranges::begin(static_cast<const remove_reference_t
<_Tp
>&>(__t
)); }
184 requires is_rvalue_reference_v
<_Tp
&&>
185 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
186 constexpr auto operator()(_Tp
&& __t
) const
187 noexcept(noexcept(ranges::begin(static_cast<const _Tp
&&>(__t
))))
188 -> decltype( ranges::begin(static_cast<const _Tp
&&>(__t
)))
189 { return ranges::begin(static_cast<const _Tp
&&>(__t
)); }
191 } // namespace __cbegin
193 inline namespace __cpo
{
194 inline constexpr auto cbegin
= __cbegin::__fn
{};
196 } // namespace ranges
198 // [range.access.cend]
204 requires is_lvalue_reference_v
<_Tp
&&>
205 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
206 constexpr auto operator()(_Tp
&& __t
) const
207 noexcept(noexcept(ranges::end(static_cast<const remove_reference_t
<_Tp
>&>(__t
))))
208 -> decltype( ranges::end(static_cast<const remove_reference_t
<_Tp
>&>(__t
)))
209 { return ranges::end(static_cast<const remove_reference_t
<_Tp
>&>(__t
)); }
212 requires is_rvalue_reference_v
<_Tp
&&>
213 [[nodiscard
]] _LIBCPP_HIDE_FROM_ABI
214 constexpr auto operator()(_Tp
&& __t
) const
215 noexcept(noexcept(ranges::end(static_cast<const _Tp
&&>(__t
))))
216 -> decltype( ranges::end(static_cast<const _Tp
&&>(__t
)))
217 { return ranges::end(static_cast<const _Tp
&&>(__t
)); }
219 } // namespace __cend
221 inline namespace __cpo
{
222 inline constexpr auto cend
= __cend::__fn
{};
224 } // namespace ranges
226 #endif // _LIBCPP_STD_VER >= 20
228 _LIBCPP_END_NAMESPACE_STD
230 #endif // _LIBCPP___RANGES_ACCESS_H