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_SPAN |
11 | #define _LIBCPP_SPAN |
12 | |
13 | /* |
14 | span synopsis |
15 | |
16 | namespace std { |
17 | |
18 | // constants |
19 | inline constexpr size_t dynamic_extent = numeric_limits<size_t>::max(); |
20 | |
21 | template<class T> |
22 | concept integral-constant-like = // exposition only, since C++26 |
23 | is_integral_v<decltype(T::value)> && |
24 | !is_same_v<bool, remove_const_t<decltype(T::value)>> && |
25 | convertible_to<T, decltype(T::value)> && |
26 | equality_comparable_with<T, decltype(T::value)> && |
27 | bool_constant<T() == T::value>::value && |
28 | bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value; |
29 | |
30 | template<class T> |
31 | constexpr size_t maybe-static-ext = dynamic_extent; // exposition only, since C++26 |
32 | template<integral-constant-like T> |
33 | constexpr size_t maybe-static-ext<T> = {T::value}; |
34 | |
35 | // [views.span], class template span |
36 | template <class ElementType, size_t Extent = dynamic_extent> |
37 | class span; |
38 | |
39 | template<class ElementType, size_t Extent> |
40 | inline constexpr bool ranges::enable_view<span<ElementType, Extent>> = true; |
41 | |
42 | template<class ElementType, size_t Extent> |
43 | inline constexpr bool ranges::enable_borrowed_range<span<ElementType, Extent>> = true; |
44 | |
45 | // [span.objectrep], views of object representation |
46 | template <class ElementType, size_t Extent> |
47 | span<const byte, ((Extent == dynamic_extent) ? dynamic_extent : |
48 | (sizeof(ElementType) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept; |
49 | |
50 | template <class ElementType, size_t Extent> |
51 | span< byte, ((Extent == dynamic_extent) ? dynamic_extent : |
52 | (sizeof(ElementType) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept; |
53 | |
54 | |
55 | template <class ElementType, size_t Extent = dynamic_extent> |
56 | class span { |
57 | public: |
58 | // constants and types |
59 | using element_type = ElementType; |
60 | using value_type = remove_cv_t<ElementType>; |
61 | using size_type = size_t; |
62 | using difference_type = ptrdiff_t; |
63 | using pointer = element_type*; |
64 | using const_pointer = const element_type*; |
65 | using reference = element_type&; |
66 | using const_reference = const element_type&; |
67 | using iterator = implementation-defined; |
68 | using reverse_iterator = std::reverse_iterator<iterator>; |
69 | static constexpr size_type extent = Extent; |
70 | |
71 | // [span.cons], span constructors, copy, assignment, and destructor |
72 | constexpr span() noexcept; |
73 | template <class It> |
74 | constexpr explicit(Extent != dynamic_extent) span(It first, size_type count); |
75 | template <class It, class End> |
76 | constexpr explicit(Extent != dynamic_extent) span(It first, End last); |
77 | template <size_t N> |
78 | constexpr span(type_identity_t<element_type> (&arr)[N]) noexcept; |
79 | template <size_t N> |
80 | constexpr span(array<value_type, N>& arr) noexcept; |
81 | template <size_t N> |
82 | constexpr span(const array<value_type, N>& arr) noexcept; |
83 | template<class R> |
84 | constexpr explicit(Extent != dynamic_extent) span(R&& r); |
85 | constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il); // Since C++26 |
86 | constexpr span(const span& other) noexcept = default; |
87 | template <class OtherElementType, size_t OtherExtent> |
88 | constexpr explicit(Extent != dynamic_extent) span(const span<OtherElementType, OtherExtent>& s) noexcept; |
89 | constexpr span& operator=(const span& other) noexcept = default; |
90 | |
91 | // [span.sub], span subviews |
92 | template <size_t Count> |
93 | constexpr span<element_type, Count> first() const; |
94 | template <size_t Count> |
95 | constexpr span<element_type, Count> last() const; |
96 | template <size_t Offset, size_t Count = dynamic_extent> |
97 | constexpr span<element_type, see below> subspan() const; |
98 | |
99 | constexpr span<element_type, dynamic_extent> first(size_type count) const; |
100 | constexpr span<element_type, dynamic_extent> last(size_type count) const; |
101 | constexpr span<element_type, dynamic_extent> subspan(size_type offset, size_type count = dynamic_extent) const; |
102 | |
103 | // [span.obs], span observers |
104 | constexpr size_type size() const noexcept; |
105 | constexpr size_type size_bytes() const noexcept; |
106 | [[nodiscard]] constexpr bool empty() const noexcept; |
107 | |
108 | // [span.elem], span element access |
109 | constexpr reference operator[](size_type idx) const; |
110 | constexpr reference at(size_type idx) const; // since C++26 |
111 | constexpr reference front() const; |
112 | constexpr reference back() const; |
113 | constexpr pointer data() const noexcept; |
114 | |
115 | // [span.iterators], span iterator support |
116 | constexpr iterator begin() const noexcept; |
117 | constexpr iterator end() const noexcept; |
118 | constexpr reverse_iterator rbegin() const noexcept; |
119 | constexpr reverse_iterator rend() const noexcept; |
120 | |
121 | private: |
122 | pointer data_; // exposition only |
123 | size_type size_; // exposition only |
124 | }; |
125 | |
126 | template<class It, class EndOrSize> |
127 | span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>; // until C++26 |
128 | template<class It, class EndOrSize> |
129 | span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>, maybe-static-ext<EndOrSize>>; // since C++26 |
130 | |
131 | template<class T, size_t N> |
132 | span(T (&)[N]) -> span<T, N>; |
133 | |
134 | template<class T, size_t N> |
135 | span(array<T, N>&) -> span<T, N>; |
136 | |
137 | template<class T, size_t N> |
138 | span(const array<T, N>&) -> span<const T, N>; |
139 | |
140 | template<class R> |
141 | span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>; |
142 | |
143 | } // namespace std |
144 | |
145 | */ |
146 | |
147 | #if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) |
148 | # include <__cxx03/__config> |
149 | #else |
150 | # include <__assert> |
151 | # include <__concepts/convertible_to.h> |
152 | # include <__concepts/equality_comparable.h> |
153 | # include <__config> |
154 | # include <__cstddef/byte.h> |
155 | # include <__cstddef/ptrdiff_t.h> |
156 | # include <__fwd/array.h> |
157 | # include <__fwd/span.h> |
158 | # include <__iterator/bounded_iter.h> |
159 | # include <__iterator/concepts.h> |
160 | # include <__iterator/iterator_traits.h> |
161 | # include <__iterator/reverse_iterator.h> |
162 | # include <__iterator/wrap_iter.h> |
163 | # include <__memory/pointer_traits.h> |
164 | # include <__ranges/concepts.h> |
165 | # include <__ranges/data.h> |
166 | # include <__ranges/enable_borrowed_range.h> |
167 | # include <__ranges/enable_view.h> |
168 | # include <__ranges/size.h> |
169 | # include <__type_traits/integral_constant.h> |
170 | # include <__type_traits/is_array.h> |
171 | # include <__type_traits/is_const.h> |
172 | # include <__type_traits/is_convertible.h> |
173 | # include <__type_traits/is_integral.h> |
174 | # include <__type_traits/is_same.h> |
175 | # include <__type_traits/remove_const.h> |
176 | # include <__type_traits/remove_cv.h> |
177 | # include <__type_traits/remove_cvref.h> |
178 | # include <__type_traits/remove_reference.h> |
179 | # include <__type_traits/type_identity.h> |
180 | # include <__utility/forward.h> |
181 | # include <initializer_list> |
182 | # include <stdexcept> |
183 | # include <version> |
184 | |
185 | // standard-mandated includes |
186 | |
187 | // [iterator.range] |
188 | # include <__iterator/access.h> |
189 | # include <__iterator/data.h> |
190 | # include <__iterator/empty.h> |
191 | # include <__iterator/reverse_access.h> |
192 | # include <__iterator/size.h> |
193 | |
194 | # if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
195 | # pragma GCC system_header |
196 | # endif |
197 | |
198 | _LIBCPP_PUSH_MACROS |
199 | # include <__undef_macros> |
200 | |
201 | _LIBCPP_BEGIN_NAMESPACE_STD |
202 | |
203 | # if _LIBCPP_STD_VER >= 20 |
204 | |
205 | template <class _Tp> |
206 | struct __is_std_span : false_type {}; |
207 | |
208 | template <class _Tp, size_t _Sz> |
209 | struct __is_std_span<span<_Tp, _Sz>> : true_type {}; |
210 | |
211 | template <class _Range, class _ElementType> |
212 | concept __span_compatible_range = |
213 | !__is_std_span<remove_cvref_t<_Range>>::value && // |
214 | ranges::contiguous_range<_Range> && // |
215 | ranges::sized_range<_Range> && // |
216 | (ranges::borrowed_range<_Range> || is_const_v<_ElementType>) && // |
217 | !__is_std_array_v<remove_cvref_t<_Range>> && // |
218 | !is_array_v<remove_cvref_t<_Range>> && // |
219 | is_convertible_v<remove_reference_t<ranges::range_reference_t<_Range>> (*)[], _ElementType (*)[]>; |
220 | |
221 | template <class _From, class _To> |
222 | concept __span_array_convertible = is_convertible_v<_From (*)[], _To (*)[]>; |
223 | |
224 | template <class _It, class _Tp> |
225 | concept __span_compatible_iterator = |
226 | contiguous_iterator<_It> && __span_array_convertible<remove_reference_t<iter_reference_t<_It>>, _Tp>; |
227 | |
228 | template <class _Sentinel, class _It> |
229 | concept __span_compatible_sentinel_for = sized_sentinel_for<_Sentinel, _It> && !is_convertible_v<_Sentinel, size_t>; |
230 | |
231 | template <typename _Tp, size_t _Extent> |
232 | class span { |
233 | public: |
234 | // constants and types |
235 | using element_type = _Tp; |
236 | using value_type = remove_cv_t<_Tp>; |
237 | using size_type = size_t; |
238 | using difference_type = ptrdiff_t; |
239 | using pointer = _Tp*; |
240 | using const_pointer = const _Tp*; |
241 | using reference = _Tp&; |
242 | using const_reference = const _Tp&; |
243 | # ifdef _LIBCPP_ABI_BOUNDED_ITERATORS |
244 | using iterator = __bounded_iter<pointer>; |
245 | # else |
246 | using iterator = __wrap_iter<pointer>; |
247 | # endif |
248 | using reverse_iterator = std::reverse_iterator<iterator>; |
249 | |
250 | static constexpr size_type extent = _Extent; |
251 | |
252 | // [span.cons], span constructors, copy, assignment, and destructor |
253 | template <size_t _Sz = _Extent> |
254 | requires(_Sz == 0) |
255 | _LIBCPP_HIDE_FROM_ABI constexpr span() noexcept : __data_{nullptr} {} |
256 | |
257 | # if _LIBCPP_STD_VER >= 26 |
258 | _LIBCPP_HIDE_FROM_ABI constexpr explicit span(std::initializer_list<value_type> __il) |
259 | requires is_const_v<element_type> |
260 | : __data_{__il.begin()} { |
261 | _LIBCPP_ASSERT_VALID_INPUT_RANGE( |
262 | _Extent == __il.size(), "Size mismatch in span's constructor _Extent != __il.size()." ); |
263 | } |
264 | # endif |
265 | |
266 | constexpr span(const span&) noexcept = default; |
267 | constexpr span& operator=(const span&) noexcept = default; |
268 | |
269 | template <__span_compatible_iterator<element_type> _It> |
270 | _LIBCPP_HIDE_FROM_ABI constexpr explicit span(_It __first, size_type __count) : __data_{std::to_address(__first)} { |
271 | (void)__count; |
272 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Extent == __count, "size mismatch in span's constructor (iterator, len)" ); |
273 | _LIBCPP_ASSERT_VALID_INPUT_RANGE(__count == 0 || std::to_address(__first) != nullptr, |
274 | "passed nullptr with non-zero length in span's constructor (iterator, len)" ); |
275 | } |
276 | |
277 | template <__span_compatible_iterator<element_type> _It, __span_compatible_sentinel_for<_It> _End> |
278 | _LIBCPP_HIDE_FROM_ABI constexpr explicit span(_It __first, _End __last) : __data_{std::to_address(__first)} { |
279 | // [span.cons]/10 |
280 | // Throws: When and what last - first throws. |
281 | [[maybe_unused]] auto __dist = __last - __first; |
282 | _LIBCPP_ASSERT_VALID_INPUT_RANGE(__dist >= 0, "invalid range in span's constructor (iterator, sentinel)" ); |
283 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( |
284 | __dist == _Extent, "invalid range in span's constructor (iterator, sentinel): last - first != extent" ); |
285 | } |
286 | |
287 | _LIBCPP_HIDE_FROM_ABI constexpr span(type_identity_t<element_type> (&__arr)[_Extent]) noexcept : __data_{__arr} {} |
288 | |
289 | template <__span_array_convertible<element_type> _OtherElementType> |
290 | _LIBCPP_HIDE_FROM_ABI constexpr span(array<_OtherElementType, _Extent>& __arr) noexcept : __data_{__arr.data()} {} |
291 | |
292 | template <class _OtherElementType> |
293 | requires __span_array_convertible<const _OtherElementType, element_type> |
294 | _LIBCPP_HIDE_FROM_ABI constexpr span(const array<_OtherElementType, _Extent>& __arr) noexcept |
295 | : __data_{__arr.data()} {} |
296 | |
297 | template <__span_compatible_range<element_type> _Range> |
298 | _LIBCPP_HIDE_FROM_ABI constexpr explicit span(_Range&& __r) : __data_{ranges::data(__r)} { |
299 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(ranges::size(__r) == _Extent, "size mismatch in span's constructor (range)" ); |
300 | } |
301 | |
302 | template <__span_array_convertible<element_type> _OtherElementType> |
303 | _LIBCPP_HIDE_FROM_ABI constexpr span(const span<_OtherElementType, _Extent>& __other) noexcept |
304 | : __data_{__other.data()} {} |
305 | |
306 | template <__span_array_convertible<element_type> _OtherElementType> |
307 | _LIBCPP_HIDE_FROM_ABI constexpr explicit span(const span<_OtherElementType, dynamic_extent>& __other) noexcept |
308 | : __data_{__other.data()} { |
309 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Extent == __other.size(), "size mismatch in span's constructor (other span)" ); |
310 | } |
311 | |
312 | template <size_t _Count> |
313 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> first() const noexcept { |
314 | static_assert(_Count <= _Extent, "span<T, N>::first<Count>(): Count out of range" ); |
315 | return span<element_type, _Count>{data(), _Count}; |
316 | } |
317 | |
318 | template <size_t _Count> |
319 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> last() const noexcept { |
320 | static_assert(_Count <= _Extent, "span<T, N>::last<Count>(): Count out of range" ); |
321 | return span<element_type, _Count>{data() + size() - _Count, _Count}; |
322 | } |
323 | |
324 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept { |
325 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T, N>::first(count): count out of range" ); |
326 | return {data(), __count}; |
327 | } |
328 | |
329 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept { |
330 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T, N>::last(count): count out of range" ); |
331 | return {data() + size() - __count, __count}; |
332 | } |
333 | |
334 | template <size_t _Offset, size_t _Count = dynamic_extent> |
335 | _LIBCPP_HIDE_FROM_ABI constexpr auto |
336 | subspan() const noexcept -> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset> { |
337 | static_assert(_Offset <= _Extent, "span<T, N>::subspan<Offset, Count>(): Offset out of range" ); |
338 | static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset, |
339 | "span<T, N>::subspan<Offset, Count>(): Offset + Count out of range" ); |
340 | |
341 | using _ReturnType = span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>; |
342 | return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; |
343 | } |
344 | |
345 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> |
346 | subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept { |
347 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__offset <= size(), "span<T, N>::subspan(offset, count): offset out of range" ); |
348 | if (__count == dynamic_extent) |
349 | return {data() + __offset, size() - __offset}; |
350 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( |
351 | __count <= size() - __offset, "span<T, N>::subspan(offset, count): offset + count out of range" ); |
352 | return {data() + __offset, __count}; |
353 | } |
354 | |
355 | _LIBCPP_HIDE_FROM_ABI constexpr size_type size() const noexcept { return _Extent; } |
356 | _LIBCPP_HIDE_FROM_ABI constexpr size_type size_bytes() const noexcept { return _Extent * sizeof(element_type); } |
357 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const noexcept { return _Extent == 0; } |
358 | |
359 | _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](size_type __idx) const noexcept { |
360 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < size(), "span<T, N>::operator[](index): index out of range" ); |
361 | return __data_[__idx]; |
362 | } |
363 | |
364 | # if _LIBCPP_STD_VER >= 26 |
365 | _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const { |
366 | if (__index >= size()) |
367 | std::__throw_out_of_range("span" ); |
368 | return __data_[__index]; |
369 | } |
370 | # endif |
371 | |
372 | _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept { |
373 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::front() on empty span" ); |
374 | return __data_[0]; |
375 | } |
376 | |
377 | _LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept { |
378 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::back() on empty span" ); |
379 | return __data_[size() - 1]; |
380 | } |
381 | |
382 | _LIBCPP_HIDE_FROM_ABI constexpr pointer data() const noexcept { return __data_; } |
383 | |
384 | // [span.iter], span iterator support |
385 | _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() const noexcept { |
386 | # ifdef _LIBCPP_ABI_BOUNDED_ITERATORS |
387 | return std::__make_bounded_iter(data(), data(), data() + size()); |
388 | # else |
389 | return iterator(data()); |
390 | # endif |
391 | } |
392 | _LIBCPP_HIDE_FROM_ABI constexpr iterator end() const noexcept { |
393 | # ifdef _LIBCPP_ABI_BOUNDED_ITERATORS |
394 | return std::__make_bounded_iter(data() + size(), data(), data() + size()); |
395 | # else |
396 | return iterator(data() + size()); |
397 | # endif |
398 | } |
399 | _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } |
400 | _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } |
401 | |
402 | _LIBCPP_HIDE_FROM_ABI span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept { |
403 | return span<const byte, _Extent * sizeof(element_type)>{reinterpret_cast<const byte*>(data()), size_bytes()}; |
404 | } |
405 | |
406 | _LIBCPP_HIDE_FROM_ABI span<byte, _Extent * sizeof(element_type)> __as_writable_bytes() const noexcept { |
407 | return span<byte, _Extent * sizeof(element_type)>{reinterpret_cast<byte*>(data()), size_bytes()}; |
408 | } |
409 | |
410 | private: |
411 | pointer __data_; |
412 | }; |
413 | |
414 | template <typename _Tp> |
415 | class span<_Tp, dynamic_extent> { |
416 | public: |
417 | // constants and types |
418 | using element_type = _Tp; |
419 | using value_type = remove_cv_t<_Tp>; |
420 | using size_type = size_t; |
421 | using difference_type = ptrdiff_t; |
422 | using pointer = _Tp*; |
423 | using const_pointer = const _Tp*; |
424 | using reference = _Tp&; |
425 | using const_reference = const _Tp&; |
426 | # ifdef _LIBCPP_ABI_BOUNDED_ITERATORS |
427 | using iterator = __bounded_iter<pointer>; |
428 | # else |
429 | using iterator = __wrap_iter<pointer>; |
430 | # endif |
431 | using reverse_iterator = std::reverse_iterator<iterator>; |
432 | |
433 | static constexpr size_type extent = dynamic_extent; |
434 | |
435 | // [span.cons], span constructors, copy, assignment, and destructor |
436 | _LIBCPP_HIDE_FROM_ABI constexpr span() noexcept : __data_{nullptr}, __size_{0} {} |
437 | |
438 | # if _LIBCPP_STD_VER >= 26 |
439 | _LIBCPP_HIDE_FROM_ABI constexpr span(std::initializer_list<value_type> __il) |
440 | requires is_const_v<element_type> |
441 | : __data_{__il.begin()}, __size_{__il.size()} {} |
442 | # endif |
443 | |
444 | constexpr span(const span&) noexcept = default; |
445 | constexpr span& operator=(const span&) noexcept = default; |
446 | |
447 | template <__span_compatible_iterator<element_type> _It> |
448 | _LIBCPP_HIDE_FROM_ABI constexpr span(_It __first, size_type __count) |
449 | : __data_{std::to_address(__first)}, __size_{__count} { |
450 | _LIBCPP_ASSERT_VALID_INPUT_RANGE(__count == 0 || std::to_address(__first) != nullptr, |
451 | "passed nullptr with non-zero length in span's constructor (iterator, len)" ); |
452 | } |
453 | |
454 | template <__span_compatible_iterator<element_type> _It, __span_compatible_sentinel_for<_It> _End> |
455 | _LIBCPP_HIDE_FROM_ABI constexpr span(_It __first, _End __last) |
456 | : __data_(std::to_address(__first)), __size_(__last - __first) { |
457 | _LIBCPP_ASSERT_VALID_INPUT_RANGE(__last - __first >= 0, "invalid range in span's constructor (iterator, sentinel)" ); |
458 | } |
459 | |
460 | template <size_t _Sz> |
461 | _LIBCPP_HIDE_FROM_ABI constexpr span(type_identity_t<element_type> (&__arr)[_Sz]) noexcept |
462 | : __data_{__arr}, __size_{_Sz} {} |
463 | |
464 | template <__span_array_convertible<element_type> _OtherElementType, size_t _Sz> |
465 | _LIBCPP_HIDE_FROM_ABI constexpr span(array<_OtherElementType, _Sz>& __arr) noexcept |
466 | : __data_{__arr.data()}, __size_{_Sz} {} |
467 | |
468 | template <class _OtherElementType, size_t _Sz> |
469 | requires __span_array_convertible<const _OtherElementType, element_type> |
470 | _LIBCPP_HIDE_FROM_ABI constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept |
471 | : __data_{__arr.data()}, __size_{_Sz} {} |
472 | |
473 | template <__span_compatible_range<element_type> _Range> |
474 | _LIBCPP_HIDE_FROM_ABI constexpr span(_Range&& __r) : __data_(ranges::data(__r)), __size_{ranges::size(__r)} {} |
475 | |
476 | template <__span_array_convertible<element_type> _OtherElementType, size_t _OtherExtent> |
477 | _LIBCPP_HIDE_FROM_ABI constexpr span(const span<_OtherElementType, _OtherExtent>& __other) noexcept |
478 | : __data_{__other.data()}, __size_{__other.size()} {} |
479 | |
480 | template <size_t _Count> |
481 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> first() const noexcept { |
482 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count <= size(), "span<T>::first<Count>(): Count out of range" ); |
483 | return span<element_type, _Count>{data(), _Count}; |
484 | } |
485 | |
486 | template <size_t _Count> |
487 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> last() const noexcept { |
488 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count <= size(), "span<T>::last<Count>(): Count out of range" ); |
489 | return span<element_type, _Count>{data() + size() - _Count, _Count}; |
490 | } |
491 | |
492 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept { |
493 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T>::first(count): count out of range" ); |
494 | return {data(), __count}; |
495 | } |
496 | |
497 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept { |
498 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T>::last(count): count out of range" ); |
499 | return {data() + size() - __count, __count}; |
500 | } |
501 | |
502 | template <size_t _Offset, size_t _Count = dynamic_extent> |
503 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> subspan() const noexcept { |
504 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Offset <= size(), "span<T>::subspan<Offset, Count>(): Offset out of range" ); |
505 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count == dynamic_extent || _Count <= size() - _Offset, |
506 | "span<T>::subspan<Offset, Count>(): Offset + Count out of range" ); |
507 | return span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; |
508 | } |
509 | |
510 | constexpr span<element_type, dynamic_extent> _LIBCPP_HIDE_FROM_ABI |
511 | subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept { |
512 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__offset <= size(), "span<T>::subspan(offset, count): offset out of range" ); |
513 | if (__count == dynamic_extent) |
514 | return {data() + __offset, size() - __offset}; |
515 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( |
516 | __count <= size() - __offset, "span<T>::subspan(offset, count): offset + count out of range" ); |
517 | return {data() + __offset, __count}; |
518 | } |
519 | |
520 | _LIBCPP_HIDE_FROM_ABI constexpr size_type size() const noexcept { return __size_; } |
521 | _LIBCPP_HIDE_FROM_ABI constexpr size_type size_bytes() const noexcept { return __size_ * sizeof(element_type); } |
522 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const noexcept { return __size_ == 0; } |
523 | |
524 | _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](size_type __idx) const noexcept { |
525 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < size(), "span<T>::operator[](index): index out of range" ); |
526 | return __data_[__idx]; |
527 | } |
528 | |
529 | # if _LIBCPP_STD_VER >= 26 |
530 | _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const { |
531 | if (__index >= size()) |
532 | std::__throw_out_of_range("span" ); |
533 | return __data_[__index]; |
534 | } |
535 | # endif |
536 | |
537 | _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept { |
538 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::front() on empty span" ); |
539 | return __data_[0]; |
540 | } |
541 | |
542 | _LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept { |
543 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::back() on empty span" ); |
544 | return __data_[size() - 1]; |
545 | } |
546 | |
547 | _LIBCPP_HIDE_FROM_ABI constexpr pointer data() const noexcept { return __data_; } |
548 | |
549 | // [span.iter], span iterator support |
550 | _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() const noexcept { |
551 | # ifdef _LIBCPP_ABI_BOUNDED_ITERATORS |
552 | return std::__make_bounded_iter(data(), data(), data() + size()); |
553 | # else |
554 | return iterator(data()); |
555 | # endif |
556 | } |
557 | _LIBCPP_HIDE_FROM_ABI constexpr iterator end() const noexcept { |
558 | # ifdef _LIBCPP_ABI_BOUNDED_ITERATORS |
559 | return std::__make_bounded_iter(data() + size(), data(), data() + size()); |
560 | # else |
561 | return iterator(data() + size()); |
562 | # endif |
563 | } |
564 | _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } |
565 | _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } |
566 | |
567 | _LIBCPP_HIDE_FROM_ABI span<const byte, dynamic_extent> __as_bytes() const noexcept { |
568 | return {reinterpret_cast<const byte*>(data()), size_bytes()}; |
569 | } |
570 | |
571 | _LIBCPP_HIDE_FROM_ABI span<byte, dynamic_extent> __as_writable_bytes() const noexcept { |
572 | return {reinterpret_cast<byte*>(data()), size_bytes()}; |
573 | } |
574 | |
575 | private: |
576 | pointer __data_; |
577 | size_type __size_; |
578 | }; |
579 | |
580 | template <class _Tp, size_t _Extent> |
581 | inline constexpr bool ranges::enable_borrowed_range<span<_Tp, _Extent> > = true; |
582 | |
583 | template <class _ElementType, size_t _Extent> |
584 | inline constexpr bool ranges::enable_view<span<_ElementType, _Extent>> = true; |
585 | |
586 | // as_bytes & as_writable_bytes |
587 | template <class _Tp, size_t _Extent> |
588 | _LIBCPP_HIDE_FROM_ABI auto as_bytes(span<_Tp, _Extent> __s) noexcept { |
589 | return __s.__as_bytes(); |
590 | } |
591 | |
592 | template <class _Tp, size_t _Extent> |
593 | requires(!is_const_v<_Tp>) |
594 | _LIBCPP_HIDE_FROM_ABI auto as_writable_bytes(span<_Tp, _Extent> __s) noexcept { |
595 | return __s.__as_writable_bytes(); |
596 | } |
597 | |
598 | # if _LIBCPP_STD_VER >= 26 |
599 | template <class _Tp> |
600 | concept __integral_constant_like = |
601 | is_integral_v<decltype(_Tp::value)> && !is_same_v<bool, remove_const_t<decltype(_Tp::value)>> && |
602 | convertible_to<_Tp, decltype(_Tp::value)> && equality_comparable_with<_Tp, decltype(_Tp::value)> && |
603 | bool_constant<_Tp() == _Tp::value>::value && |
604 | bool_constant<static_cast<decltype(_Tp::value)>(_Tp()) == _Tp::value>::value; |
605 | |
606 | template <class _Tp> |
607 | inline constexpr size_t __maybe_static_ext = dynamic_extent; |
608 | |
609 | template <__integral_constant_like _Tp> |
610 | inline constexpr size_t __maybe_static_ext<_Tp> = {_Tp::value}; |
611 | |
612 | template <contiguous_iterator _It, class _EndOrSize> |
613 | span(_It, _EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>, __maybe_static_ext<_EndOrSize>>; |
614 | # else |
615 | template <contiguous_iterator _It, class _EndOrSize> |
616 | span(_It, _EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>; |
617 | # endif |
618 | |
619 | template <class _Tp, size_t _Sz> |
620 | span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>; |
621 | |
622 | template <class _Tp, size_t _Sz> |
623 | span(array<_Tp, _Sz>&) -> span<_Tp, _Sz>; |
624 | |
625 | template <class _Tp, size_t _Sz> |
626 | span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>; |
627 | |
628 | template <ranges::contiguous_range _Range> |
629 | span(_Range&&) -> span<remove_reference_t<ranges::range_reference_t<_Range>>>; |
630 | |
631 | # endif // _LIBCPP_STD_VER >= 20 |
632 | |
633 | _LIBCPP_END_NAMESPACE_STD |
634 | |
635 | _LIBCPP_POP_MACROS |
636 | |
637 | # if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 |
638 | # include <array> |
639 | # include <concepts> |
640 | # include <functional> |
641 | # include <iterator> |
642 | # include <type_traits> |
643 | # endif |
644 | #endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS) |
645 | |
646 | #endif // _LIBCPP_SPAN |
647 | |