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