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 10 #ifndef _LIBCPP___RANGES_VIEW_INTERFACE_H 11 #define _LIBCPP___RANGES_VIEW_INTERFACE_H 12 13 #include <__assert> 14 #include <__concepts/derived_from.h> 15 #include <__concepts/same_as.h> 16 #include <__config> 17 #include <__iterator/concepts.h> 18 #include <__iterator/iterator_traits.h> 19 #include <__iterator/prev.h> 20 #include <__memory/pointer_traits.h> 21 #include <__ranges/access.h> 22 #include <__ranges/concepts.h> 23 #include <__ranges/empty.h> 24 #include <__type_traits/is_class.h> 25 #include <__type_traits/make_unsigned.h> 26 #include <__type_traits/remove_cv.h> 27 28 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 29 # pragma GCC system_header 30 #endif 31 32 _LIBCPP_BEGIN_NAMESPACE_STD 33 34 #if _LIBCPP_STD_VER >= 20 35 36 namespace ranges { 37 38 template<class _Derived> 39 requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> 40 class view_interface { 41 _LIBCPP_HIDE_FROM_ABI 42 constexpr _Derived& __derived() noexcept { 43 static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>); 44 return static_cast<_Derived&>(*this); 45 } 46 47 _LIBCPP_HIDE_FROM_ABI 48 constexpr _Derived const& __derived() const noexcept { 49 static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>); 50 return static_cast<_Derived const&>(*this); 51 } 52 53 public: 54 template<class _D2 = _Derived> 55 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() 56 requires forward_range<_D2> 57 { 58 return ranges::begin(__derived()) == ranges::end(__derived()); 59 } 60 61 template<class _D2 = _Derived> 62 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const 63 requires forward_range<const _D2> 64 { 65 return ranges::begin(__derived()) == ranges::end(__derived()); 66 } 67 68 template<class _D2 = _Derived> 69 _LIBCPP_HIDE_FROM_ABI 70 constexpr explicit operator bool() 71 requires requires (_D2& __t) { ranges::empty(__t); } 72 { 73 return !ranges::empty(__derived()); 74 } 75 76 template<class _D2 = _Derived> 77 _LIBCPP_HIDE_FROM_ABI 78 constexpr explicit operator bool() const 79 requires requires (const _D2& __t) { ranges::empty(__t); } 80 { 81 return !ranges::empty(__derived()); 82 } 83 84 template<class _D2 = _Derived> 85 _LIBCPP_HIDE_FROM_ABI 86 constexpr auto data() 87 requires contiguous_iterator<iterator_t<_D2>> 88 { 89 return std::to_address(ranges::begin(__derived())); 90 } 91 92 template<class _D2 = _Derived> 93 _LIBCPP_HIDE_FROM_ABI 94 constexpr auto data() const 95 requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>> 96 { 97 return std::to_address(ranges::begin(__derived())); 98 } 99 100 template<class _D2 = _Derived> 101 _LIBCPP_HIDE_FROM_ABI 102 constexpr auto size() 103 requires forward_range<_D2> && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>> 104 { 105 return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived())); 106 } 107 108 template<class _D2 = _Derived> 109 _LIBCPP_HIDE_FROM_ABI 110 constexpr auto size() const 111 requires forward_range<const _D2> && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>> 112 { 113 return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived())); 114 } 115 116 template<class _D2 = _Derived> 117 _LIBCPP_HIDE_FROM_ABI 118 constexpr decltype(auto) front() 119 requires forward_range<_D2> 120 { 121 _LIBCPP_ASSERT_UNCATEGORIZED(!empty(), 122 "Precondition `!empty()` not satisfied. `.front()` called on an empty view."); 123 return *ranges::begin(__derived()); 124 } 125 126 template<class _D2 = _Derived> 127 _LIBCPP_HIDE_FROM_ABI 128 constexpr decltype(auto) front() const 129 requires forward_range<const _D2> 130 { 131 _LIBCPP_ASSERT_UNCATEGORIZED(!empty(), 132 "Precondition `!empty()` not satisfied. `.front()` called on an empty view."); 133 return *ranges::begin(__derived()); 134 } 135 136 template<class _D2 = _Derived> 137 _LIBCPP_HIDE_FROM_ABI 138 constexpr decltype(auto) back() 139 requires bidirectional_range<_D2> && common_range<_D2> 140 { 141 _LIBCPP_ASSERT_UNCATEGORIZED(!empty(), 142 "Precondition `!empty()` not satisfied. `.back()` called on an empty view."); 143 return *ranges::prev(ranges::end(__derived())); 144 } 145 146 template<class _D2 = _Derived> 147 _LIBCPP_HIDE_FROM_ABI 148 constexpr decltype(auto) back() const 149 requires bidirectional_range<const _D2> && common_range<const _D2> 150 { 151 _LIBCPP_ASSERT_UNCATEGORIZED(!empty(), 152 "Precondition `!empty()` not satisfied. `.back()` called on an empty view."); 153 return *ranges::prev(ranges::end(__derived())); 154 } 155 156 template<random_access_range _RARange = _Derived> 157 _LIBCPP_HIDE_FROM_ABI 158 constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) 159 { 160 return ranges::begin(__derived())[__index]; 161 } 162 163 template<random_access_range _RARange = const _Derived> 164 _LIBCPP_HIDE_FROM_ABI 165 constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const 166 { 167 return ranges::begin(__derived())[__index]; 168 } 169 }; 170 171 } // namespace ranges 172 173 #endif // _LIBCPP_STD_VER >= 20 174 175 _LIBCPP_END_NAMESPACE_STD 176 177 #endif // _LIBCPP___RANGES_VIEW_INTERFACE_H 178