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 <__ranges/size.h> |
25 | #include <__type_traits/is_class.h> |
26 | #include <__type_traits/make_unsigned.h> |
27 | #include <__type_traits/remove_cv.h> |
28 | |
29 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
30 | # pragma GCC system_header |
31 | #endif |
32 | |
33 | _LIBCPP_BEGIN_NAMESPACE_STD |
34 | |
35 | #if _LIBCPP_STD_VER >= 20 |
36 | |
37 | namespace ranges { |
38 | |
39 | template <class _Derived> |
40 | requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> |
41 | class view_interface { |
42 | _LIBCPP_HIDE_FROM_ABI 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 constexpr _Derived const& __derived() const noexcept { |
48 | static_assert(sizeof(_Derived) && derived_from<_Derived, view_interface> && view<_Derived>); |
49 | return static_cast<_Derived const&>(*this); |
50 | } |
51 | |
52 | public: |
53 | template <class _D2 = _Derived> |
54 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() |
55 | requires sized_range<_D2> || forward_range<_D2> |
56 | { |
57 | if constexpr (sized_range<_D2>) { |
58 | return ranges::size(__derived()) == 0; |
59 | } else { |
60 | return ranges::begin(__derived()) == ranges::end(__derived()); |
61 | } |
62 | } |
63 | |
64 | template <class _D2 = _Derived> |
65 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const |
66 | requires sized_range<const _D2> || forward_range<const _D2> |
67 | { |
68 | if constexpr (sized_range<const _D2>) { |
69 | return ranges::size(__derived()) == 0; |
70 | } else { |
71 | return ranges::begin(__derived()) == ranges::end(__derived()); |
72 | } |
73 | } |
74 | |
75 | template <class _D2 = _Derived> |
76 | _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() |
77 | requires requires(_D2& __t) { ranges::empty(__t); } |
78 | { |
79 | return !ranges::empty(__derived()); |
80 | } |
81 | |
82 | template <class _D2 = _Derived> |
83 | _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const |
84 | requires requires(const _D2& __t) { ranges::empty(__t); } |
85 | { |
86 | return !ranges::empty(__derived()); |
87 | } |
88 | |
89 | template <class _D2 = _Derived> |
90 | _LIBCPP_HIDE_FROM_ABI constexpr auto data() |
91 | requires contiguous_iterator<iterator_t<_D2>> |
92 | { |
93 | return std::to_address(ranges::begin(__derived())); |
94 | } |
95 | |
96 | template <class _D2 = _Derived> |
97 | _LIBCPP_HIDE_FROM_ABI constexpr auto data() const |
98 | requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>> |
99 | { |
100 | return std::to_address(ranges::begin(__derived())); |
101 | } |
102 | |
103 | template <class _D2 = _Derived> |
104 | _LIBCPP_HIDE_FROM_ABI constexpr auto size() |
105 | requires forward_range<_D2> && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>> |
106 | { |
107 | return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived())); |
108 | } |
109 | |
110 | template <class _D2 = _Derived> |
111 | _LIBCPP_HIDE_FROM_ABI constexpr auto size() const |
112 | requires forward_range<const _D2> && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>> |
113 | { |
114 | return std::__to_unsigned_like(ranges::end(__derived()) - ranges::begin(__derived())); |
115 | } |
116 | |
117 | template <class _D2 = _Derived> |
118 | _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) front() |
119 | requires forward_range<_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) front() const |
128 | requires forward_range<const _D2> |
129 | { |
130 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( |
131 | !empty(), "Precondition `!empty()` not satisfied. `.front()` called on an empty view." ); |
132 | return *ranges::begin(__derived()); |
133 | } |
134 | |
135 | template <class _D2 = _Derived> |
136 | _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) back() |
137 | requires bidirectional_range<_D2> && common_range<_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 <class _D2 = _Derived> |
145 | _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) back() const |
146 | requires bidirectional_range<const _D2> && common_range<const _D2> |
147 | { |
148 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( |
149 | !empty(), "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 constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) { |
155 | return ranges::begin(__derived())[__index]; |
156 | } |
157 | |
158 | template <random_access_range _RARange = const _Derived> |
159 | _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const { |
160 | return ranges::begin(__derived())[__index]; |
161 | } |
162 | }; |
163 | |
164 | } // namespace ranges |
165 | |
166 | #endif // _LIBCPP_STD_VER >= 20 |
167 | |
168 | _LIBCPP_END_NAMESPACE_STD |
169 | |
170 | #endif // _LIBCPP___RANGES_VIEW_INTERFACE_H |
171 | |