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