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 constexpr _Derived& __derived() noexcept { 42 static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>); 43 return static_cast<_Derived&>(*this); 44 } 45 46 _LIBCPP_HIDE_FROM_ABI constexpr _Derived const& __derived() const noexcept { 47 static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>); 48 return static_cast<_Derived const&>(*this); 49 } 50 51 public: 52 template <class _D2 = _Derived> 53 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() 54 requires forward_range<_D2> 55 { 56 return ranges::begin(__derived()) == ranges::end(__derived()); 57 } 58 59 template <class _D2 = _Derived> 60 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const 61 requires forward_range<const _D2> 62 { 63 return ranges::begin(__derived()) == ranges::end(__derived()); 64 } 65 66 template <class _D2 = _Derived> 67 _LIBCPP_HIDE_FROM_ABI 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 constexpr explicit operator bool() const 75 requires requires(const _D2& __t) { ranges::empty(__t); } 76 { 77 return !ranges::empty(__derived()); 78 } 79 80 template <class _D2 = _Derived> 81 _LIBCPP_HIDE_FROM_ABI constexpr auto data() 82 requires contiguous_iterator<iterator_t<_D2>> 83 { 84 return std::to_address(ranges::begin(__derived())); 85 } 86 87 template <class _D2 = _Derived> 88 _LIBCPP_HIDE_FROM_ABI constexpr auto data() const 89 requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>> 90 { 91 return std::to_address(ranges::begin(__derived())); 92 } 93 94 template <class _D2 = _Derived> 95 _LIBCPP_HIDE_FROM_ABI constexpr auto size() 96 requires forward_range<_D2> && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>> 97 { 98 return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived())); 99 } 100 101 template <class _D2 = _Derived> 102 _LIBCPP_HIDE_FROM_ABI constexpr auto size() const 103 requires forward_range<const _D2> && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _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 constexpr decltype(auto) front() 110 requires forward_range<_D2> 111 { 112 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 113 !empty(), "Precondition `!empty()` not satisfied. `.front()` called on an empty view."); 114 return *ranges::begin(__derived()); 115 } 116 117 template <class _D2 = _Derived> 118 _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) front() const 119 requires forward_range<const _D2> 120 { 121 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 122 !empty(), "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 constexpr decltype(auto) back() 128 requires bidirectional_range<_D2> && common_range<_D2> 129 { 130 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 131 !empty(), "Precondition `!empty()` not satisfied. `.back()` called on an empty view."); 132 return *ranges::prev(ranges::end(__derived())); 133 } 134 135 template <class _D2 = _Derived> 136 _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) back() const 137 requires bidirectional_range<const _D2> && common_range<const _D2> 138 { 139 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 140 !empty(), "Precondition `!empty()` not satisfied. `.back()` called on an empty view."); 141 return *ranges::prev(ranges::end(__derived())); 142 } 143 144 template <random_access_range _RARange = _Derived> 145 _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) { 146 return ranges::begin(__derived())[__index]; 147 } 148 149 template <random_access_range _RARange = const _Derived> 150 _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const { 151 return ranges::begin(__derived())[__index]; 152 } 153 }; 154 155 } // namespace ranges 156 157 #endif // _LIBCPP_STD_VER >= 20 158 159 _LIBCPP_END_NAMESPACE_STD 160 161 #endif // _LIBCPP___RANGES_VIEW_INTERFACE_H 162