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