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