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