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