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