1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 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 7 // 8 //===----------------------------------------------------------------------===// 9 #ifndef _LIBCPP___RANGES_REND_H 10 #define _LIBCPP___RANGES_REND_H 11 12 #include <__concepts/class_or_enum.h> 13 #include <__concepts/same_as.h> 14 #include <__config> 15 #include <__iterator/concepts.h> 16 #include <__iterator/readable_traits.h> 17 #include <__iterator/reverse_iterator.h> 18 #include <__ranges/access.h> 19 #include <__ranges/rbegin.h> 20 #include <__utility/auto_cast.h> 21 #include <type_traits> 22 23 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 24 # pragma GCC system_header 25 #endif 26 27 _LIBCPP_BEGIN_NAMESPACE_STD 28 29 #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) 30 31 // [range.access.rend] 32 33 namespace ranges { 34 namespace __rend { 35 template <class _Tp> 36 concept __member_rend = 37 __can_borrow<_Tp> && 38 __workaround_52970<_Tp> && 39 requires(_Tp&& __t) { 40 ranges::rbegin(__t); 41 { _LIBCPP_AUTO_CAST(__t.rend()) } -> sentinel_for<decltype(ranges::rbegin(__t))>; 42 }; 43 44 void rend(auto&) = delete; 45 void rend(const auto&) = delete; 46 47 template <class _Tp> 48 concept __unqualified_rend = 49 !__member_rend<_Tp> && 50 __can_borrow<_Tp> && 51 __class_or_enum<remove_cvref_t<_Tp>> && 52 requires(_Tp&& __t) { 53 ranges::rbegin(__t); 54 { _LIBCPP_AUTO_CAST(rend(__t)) } -> sentinel_for<decltype(ranges::rbegin(__t))>; 55 }; 56 57 template <class _Tp> 58 concept __can_reverse = 59 __can_borrow<_Tp> && 60 !__member_rend<_Tp> && 61 !__unqualified_rend<_Tp> && 62 requires(_Tp&& __t) { 63 { ranges::begin(__t) } -> same_as<decltype(ranges::end(__t))>; 64 { ranges::begin(__t) } -> bidirectional_iterator; 65 }; 66 67 class __fn { 68 public: 69 template <class _Tp> 70 requires __member_rend<_Tp> 71 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const 72 noexcept(noexcept(_LIBCPP_AUTO_CAST(__t.rend()))) 73 { 74 return _LIBCPP_AUTO_CAST(__t.rend()); 75 } 76 77 template <class _Tp> 78 requires __unqualified_rend<_Tp> 79 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const 80 noexcept(noexcept(_LIBCPP_AUTO_CAST(rend(__t)))) 81 { 82 return _LIBCPP_AUTO_CAST(rend(__t)); 83 } 84 85 template <class _Tp> 86 requires __can_reverse<_Tp> 87 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const 88 noexcept(noexcept(ranges::begin(__t))) 89 { 90 return std::make_reverse_iterator(ranges::begin(__t)); 91 } 92 93 void operator()(auto&&) const = delete; 94 }; 95 } // namespace __rend 96 97 inline namespace __cpo { 98 inline constexpr auto rend = __rend::__fn{}; 99 } // namespace __cpo 100 } // namespace ranges 101 102 // [range.access.crend] 103 104 namespace ranges { 105 namespace __crend { 106 struct __fn { 107 template <class _Tp> 108 requires is_lvalue_reference_v<_Tp&&> 109 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 110 constexpr auto operator()(_Tp&& __t) const 111 noexcept(noexcept(ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t)))) 112 -> decltype( ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t))) 113 { return ranges::rend(static_cast<const remove_reference_t<_Tp>&>(__t)); } 114 115 template <class _Tp> 116 requires is_rvalue_reference_v<_Tp&&> 117 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI 118 constexpr auto operator()(_Tp&& __t) const 119 noexcept(noexcept(ranges::rend(static_cast<const _Tp&&>(__t)))) 120 -> decltype( ranges::rend(static_cast<const _Tp&&>(__t))) 121 { return ranges::rend(static_cast<const _Tp&&>(__t)); } 122 }; 123 } // namespace __crend 124 125 inline namespace __cpo { 126 inline constexpr auto crend = __crend::__fn{}; 127 } // namespace __cpo 128 } // namespace ranges 129 130 #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) 131 132 _LIBCPP_END_NAMESPACE_STD 133 134 #endif // _LIBCPP___RANGES_REND_H 135