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 | #include <__assert> |
148 | #include <__concepts/convertible_to.h> |
149 | #include <__concepts/equality_comparable.h> |
150 | #include <__config> |
151 | #include <__fwd/array.h> |
152 | #include <__fwd/span.h> |
153 | #include <__iterator/bounded_iter.h> |
154 | #include <__iterator/concepts.h> |
155 | #include <__iterator/iterator_traits.h> |
156 | #include <__iterator/reverse_iterator.h> |
157 | #include <__iterator/wrap_iter.h> |
158 | #include <__memory/pointer_traits.h> |
159 | #include <__ranges/concepts.h> |
160 | #include <__ranges/data.h> |
161 | #include <__ranges/enable_borrowed_range.h> |
162 | #include <__ranges/enable_view.h> |
163 | #include <__ranges/size.h> |
164 | #include <__type_traits/integral_constant.h> |
165 | #include <__type_traits/is_array.h> |
166 | #include <__type_traits/is_const.h> |
167 | #include <__type_traits/is_convertible.h> |
168 | #include <__type_traits/is_integral.h> |
169 | #include <__type_traits/is_same.h> |
170 | #include <__type_traits/remove_const.h> |
171 | #include <__type_traits/remove_cv.h> |
172 | #include <__type_traits/remove_cvref.h> |
173 | #include <__type_traits/remove_reference.h> |
174 | #include <__type_traits/type_identity.h> |
175 | #include <__utility/forward.h> |
176 | #include <cstddef> // for byte |
177 | #include <initializer_list> |
178 | #include <stdexcept> |
179 | #include <version> |
180 | |
181 | // standard-mandated includes |
182 | |
183 | // [iterator.range] |
184 | #include <__iterator/access.h> |
185 | #include <__iterator/data.h> |
186 | #include <__iterator/empty.h> |
187 | #include <__iterator/reverse_access.h> |
188 | #include <__iterator/size.h> |
189 | |
190 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
191 | # pragma GCC system_header |
192 | #endif |
193 | |
194 | _LIBCPP_PUSH_MACROS |
195 | #include <__undef_macros> |
196 | |
197 | _LIBCPP_BEGIN_NAMESPACE_STD |
198 | |
199 | #if _LIBCPP_STD_VER >= 20 |
200 | |
201 | template <class _Tp> |
202 | struct __is_std_span : false_type {}; |
203 | |
204 | template <class _Tp, size_t _Sz> |
205 | struct __is_std_span<span<_Tp, _Sz>> : true_type {}; |
206 | |
207 | template <class _Range, class _ElementType> |
208 | concept __span_compatible_range = |
209 | !__is_std_span<remove_cvref_t<_Range>>::value && // |
210 | ranges::contiguous_range<_Range> && // |
211 | ranges::sized_range<_Range> && // |
212 | (ranges::borrowed_range<_Range> || is_const_v<_ElementType>) && // |
213 | !__is_std_array<remove_cvref_t<_Range>>::value && // |
214 | !is_array_v<remove_cvref_t<_Range>> && // |
215 | is_convertible_v<remove_reference_t<ranges::range_reference_t<_Range>> (*)[], _ElementType (*)[]>; |
216 | |
217 | template <class _From, class _To> |
218 | concept __span_array_convertible = is_convertible_v<_From (*)[], _To (*)[]>; |
219 | |
220 | template <class _It, class _Tp> |
221 | concept __span_compatible_iterator = |
222 | contiguous_iterator<_It> && __span_array_convertible<remove_reference_t<iter_reference_t<_It>>, _Tp>; |
223 | |
224 | template <class _Sentinel, class _It> |
225 | concept __span_compatible_sentinel_for = sized_sentinel_for<_Sentinel, _It> && !is_convertible_v<_Sentinel, size_t>; |
226 | |
227 | template <typename _Tp, size_t _Extent> |
228 | class _LIBCPP_TEMPLATE_VIS span { |
229 | public: |
230 | // constants and types |
231 | using element_type = _Tp; |
232 | using value_type = remove_cv_t<_Tp>; |
233 | using size_type = size_t; |
234 | using difference_type = ptrdiff_t; |
235 | using pointer = _Tp*; |
236 | using const_pointer = const _Tp*; |
237 | using reference = _Tp&; |
238 | using const_reference = const _Tp&; |
239 | # ifdef _LIBCPP_ABI_BOUNDED_ITERATORS |
240 | using iterator = __bounded_iter<pointer>; |
241 | # else |
242 | using iterator = __wrap_iter<pointer>; |
243 | # endif |
244 | using reverse_iterator = std::reverse_iterator<iterator>; |
245 | |
246 | static constexpr size_type extent = _Extent; |
247 | |
248 | // [span.cons], span constructors, copy, assignment, and destructor |
249 | template <size_t _Sz = _Extent> |
250 | requires(_Sz == 0) |
251 | _LIBCPP_HIDE_FROM_ABI constexpr span() noexcept : __data_{nullptr} {} |
252 | |
253 | # if _LIBCPP_STD_VER >= 26 |
254 | _LIBCPP_HIDE_FROM_ABI constexpr explicit span(std::initializer_list<value_type> __il) |
255 | requires is_const_v<element_type> |
256 | : __data_{__il.begin()} { |
257 | _LIBCPP_ASSERT_VALID_INPUT_RANGE( |
258 | _Extent == __il.size(), "Size mismatch in span's constructor _Extent != __il.size()." ); |
259 | } |
260 | # endif |
261 | |
262 | constexpr span(const span&) noexcept = default; |
263 | constexpr span& operator=(const span&) noexcept = default; |
264 | |
265 | template <__span_compatible_iterator<element_type> _It> |
266 | _LIBCPP_HIDE_FROM_ABI constexpr explicit span(_It __first, size_type __count) : __data_{std::to_address(__first)} { |
267 | (void)__count; |
268 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Extent == __count, "size mismatch in span's constructor (iterator, len)" ); |
269 | } |
270 | |
271 | template <__span_compatible_iterator<element_type> _It, __span_compatible_sentinel_for<_It> _End> |
272 | _LIBCPP_HIDE_FROM_ABI constexpr explicit span(_It __first, _End __last) : __data_{std::to_address(__first)} { |
273 | // [span.cons]/10 |
274 | // Throws: When and what last - first throws. |
275 | [[maybe_unused]] auto __dist = __last - __first; |
276 | _LIBCPP_ASSERT_VALID_INPUT_RANGE(__dist >= 0, "invalid range in span's constructor (iterator, sentinel)" ); |
277 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( |
278 | __dist == _Extent, "invalid range in span's constructor (iterator, sentinel): last - first != extent" ); |
279 | } |
280 | |
281 | _LIBCPP_HIDE_FROM_ABI constexpr span(type_identity_t<element_type> (&__arr)[_Extent]) noexcept : __data_{__arr} {} |
282 | |
283 | template <__span_array_convertible<element_type> _OtherElementType> |
284 | _LIBCPP_HIDE_FROM_ABI constexpr span(array<_OtherElementType, _Extent>& __arr) noexcept : __data_{__arr.data()} {} |
285 | |
286 | template <class _OtherElementType> |
287 | requires __span_array_convertible<const _OtherElementType, element_type> |
288 | _LIBCPP_HIDE_FROM_ABI constexpr span(const array<_OtherElementType, _Extent>& __arr) noexcept |
289 | : __data_{__arr.data()} {} |
290 | |
291 | template <__span_compatible_range<element_type> _Range> |
292 | _LIBCPP_HIDE_FROM_ABI constexpr explicit span(_Range&& __r) : __data_{ranges::data(__r)} { |
293 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(ranges::size(__r) == _Extent, "size mismatch in span's constructor (range)" ); |
294 | } |
295 | |
296 | template <__span_array_convertible<element_type> _OtherElementType> |
297 | _LIBCPP_HIDE_FROM_ABI constexpr span(const span<_OtherElementType, _Extent>& __other) noexcept |
298 | : __data_{__other.data()} {} |
299 | |
300 | template <__span_array_convertible<element_type> _OtherElementType> |
301 | _LIBCPP_HIDE_FROM_ABI constexpr explicit span(const span<_OtherElementType, dynamic_extent>& __other) noexcept |
302 | : __data_{__other.data()} { |
303 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Extent == __other.size(), "size mismatch in span's constructor (other span)" ); |
304 | } |
305 | |
306 | template <size_t _Count> |
307 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> first() const noexcept { |
308 | static_assert(_Count <= _Extent, "span<T, N>::first<Count>(): Count out of range" ); |
309 | return span<element_type, _Count>{data(), _Count}; |
310 | } |
311 | |
312 | template <size_t _Count> |
313 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> last() const noexcept { |
314 | static_assert(_Count <= _Extent, "span<T, N>::last<Count>(): Count out of range" ); |
315 | return span<element_type, _Count>{data() + size() - _Count, _Count}; |
316 | } |
317 | |
318 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept { |
319 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T, N>::first(count): count out of range" ); |
320 | return {data(), __count}; |
321 | } |
322 | |
323 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept { |
324 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T, N>::last(count): count out of range" ); |
325 | return {data() + size() - __count, __count}; |
326 | } |
327 | |
328 | template <size_t _Offset, size_t _Count = dynamic_extent> |
329 | _LIBCPP_HIDE_FROM_ABI constexpr auto |
330 | subspan() const noexcept -> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset> { |
331 | static_assert(_Offset <= _Extent, "span<T, N>::subspan<Offset, Count>(): Offset out of range" ); |
332 | static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset, |
333 | "span<T, N>::subspan<Offset, Count>(): Offset + Count out of range" ); |
334 | |
335 | using _ReturnType = span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>; |
336 | return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; |
337 | } |
338 | |
339 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> |
340 | subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept { |
341 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__offset <= size(), "span<T, N>::subspan(offset, count): offset out of range" ); |
342 | if (__count == dynamic_extent) |
343 | return {data() + __offset, size() - __offset}; |
344 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( |
345 | __count <= size() - __offset, "span<T, N>::subspan(offset, count): offset + count out of range" ); |
346 | return {data() + __offset, __count}; |
347 | } |
348 | |
349 | _LIBCPP_HIDE_FROM_ABI constexpr size_type size() const noexcept { return _Extent; } |
350 | _LIBCPP_HIDE_FROM_ABI constexpr size_type size_bytes() const noexcept { return _Extent * sizeof(element_type); } |
351 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const noexcept { return _Extent == 0; } |
352 | |
353 | _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](size_type __idx) const noexcept { |
354 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < size(), "span<T, N>::operator[](index): index out of range" ); |
355 | return __data_[__idx]; |
356 | } |
357 | |
358 | # if _LIBCPP_STD_VER >= 26 |
359 | _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const { |
360 | if (__index >= size()) |
361 | std::__throw_out_of_range("span" ); |
362 | return __data_[__index]; |
363 | } |
364 | # endif |
365 | |
366 | _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept { |
367 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::front() on empty span" ); |
368 | return __data_[0]; |
369 | } |
370 | |
371 | _LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept { |
372 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::back() on empty span" ); |
373 | return __data_[size() - 1]; |
374 | } |
375 | |
376 | _LIBCPP_HIDE_FROM_ABI constexpr pointer data() const noexcept { return __data_; } |
377 | |
378 | // [span.iter], span iterator support |
379 | _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() const noexcept { |
380 | # ifdef _LIBCPP_ABI_BOUNDED_ITERATORS |
381 | return std::__make_bounded_iter(data(), data(), data() + size()); |
382 | # else |
383 | return iterator(data()); |
384 | # endif |
385 | } |
386 | _LIBCPP_HIDE_FROM_ABI constexpr iterator end() const noexcept { |
387 | # ifdef _LIBCPP_ABI_BOUNDED_ITERATORS |
388 | return std::__make_bounded_iter(data() + size(), data(), data() + size()); |
389 | # else |
390 | return iterator(data() + size()); |
391 | # endif |
392 | } |
393 | _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } |
394 | _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } |
395 | |
396 | _LIBCPP_HIDE_FROM_ABI span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept { |
397 | return span<const byte, _Extent * sizeof(element_type)>{reinterpret_cast<const byte*>(data()), size_bytes()}; |
398 | } |
399 | |
400 | _LIBCPP_HIDE_FROM_ABI span<byte, _Extent * sizeof(element_type)> __as_writable_bytes() const noexcept { |
401 | return span<byte, _Extent * sizeof(element_type)>{reinterpret_cast<byte*>(data()), size_bytes()}; |
402 | } |
403 | |
404 | private: |
405 | pointer __data_; |
406 | }; |
407 | |
408 | template <typename _Tp> |
409 | class _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> { |
410 | public: |
411 | // constants and types |
412 | using element_type = _Tp; |
413 | using value_type = remove_cv_t<_Tp>; |
414 | using size_type = size_t; |
415 | using difference_type = ptrdiff_t; |
416 | using pointer = _Tp*; |
417 | using const_pointer = const _Tp*; |
418 | using reference = _Tp&; |
419 | using const_reference = const _Tp&; |
420 | # ifdef _LIBCPP_ABI_BOUNDED_ITERATORS |
421 | using iterator = __bounded_iter<pointer>; |
422 | # else |
423 | using iterator = __wrap_iter<pointer>; |
424 | # endif |
425 | using reverse_iterator = std::reverse_iterator<iterator>; |
426 | |
427 | static constexpr size_type extent = dynamic_extent; |
428 | |
429 | // [span.cons], span constructors, copy, assignment, and destructor |
430 | _LIBCPP_HIDE_FROM_ABI constexpr span() noexcept : __data_{nullptr}, __size_{0} {} |
431 | |
432 | # if _LIBCPP_STD_VER >= 26 |
433 | _LIBCPP_HIDE_FROM_ABI constexpr span(std::initializer_list<value_type> __il) |
434 | requires is_const_v<element_type> |
435 | : __data_{__il.begin()}, __size_{__il.size()} {} |
436 | # endif |
437 | |
438 | constexpr span(const span&) noexcept = default; |
439 | constexpr span& operator=(const span&) noexcept = default; |
440 | |
441 | template <__span_compatible_iterator<element_type> _It> |
442 | _LIBCPP_HIDE_FROM_ABI constexpr span(_It __first, size_type __count) |
443 | : __data_{std::to_address(__first)}, __size_{__count} {} |
444 | |
445 | template <__span_compatible_iterator<element_type> _It, __span_compatible_sentinel_for<_It> _End> |
446 | _LIBCPP_HIDE_FROM_ABI constexpr span(_It __first, _End __last) |
447 | : __data_(std::to_address(__first)), __size_(__last - __first) { |
448 | _LIBCPP_ASSERT_VALID_INPUT_RANGE(__last - __first >= 0, "invalid range in span's constructor (iterator, sentinel)" ); |
449 | } |
450 | |
451 | template <size_t _Sz> |
452 | _LIBCPP_HIDE_FROM_ABI constexpr span(type_identity_t<element_type> (&__arr)[_Sz]) noexcept |
453 | : __data_{__arr}, __size_{_Sz} {} |
454 | |
455 | template <__span_array_convertible<element_type> _OtherElementType, size_t _Sz> |
456 | _LIBCPP_HIDE_FROM_ABI constexpr span(array<_OtherElementType, _Sz>& __arr) noexcept |
457 | : __data_{__arr.data()}, __size_{_Sz} {} |
458 | |
459 | template <class _OtherElementType, size_t _Sz> |
460 | requires __span_array_convertible<const _OtherElementType, element_type> |
461 | _LIBCPP_HIDE_FROM_ABI constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept |
462 | : __data_{__arr.data()}, __size_{_Sz} {} |
463 | |
464 | template <__span_compatible_range<element_type> _Range> |
465 | _LIBCPP_HIDE_FROM_ABI constexpr span(_Range&& __r) : __data_(ranges::data(__r)), __size_{ranges::size(__r)} {} |
466 | |
467 | template <__span_array_convertible<element_type> _OtherElementType, size_t _OtherExtent> |
468 | _LIBCPP_HIDE_FROM_ABI constexpr span(const span<_OtherElementType, _OtherExtent>& __other) noexcept |
469 | : __data_{__other.data()}, __size_{__other.size()} {} |
470 | |
471 | template <size_t _Count> |
472 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> first() const noexcept { |
473 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count <= size(), "span<T>::first<Count>(): Count out of range" ); |
474 | return span<element_type, _Count>{data(), _Count}; |
475 | } |
476 | |
477 | template <size_t _Count> |
478 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> last() const noexcept { |
479 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count <= size(), "span<T>::last<Count>(): Count out of range" ); |
480 | return span<element_type, _Count>{data() + size() - _Count, _Count}; |
481 | } |
482 | |
483 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept { |
484 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T>::first(count): count out of range" ); |
485 | return {data(), __count}; |
486 | } |
487 | |
488 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept { |
489 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T>::last(count): count out of range" ); |
490 | return {data() + size() - __count, __count}; |
491 | } |
492 | |
493 | template <size_t _Offset, size_t _Count = dynamic_extent> |
494 | _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> subspan() const noexcept { |
495 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Offset <= size(), "span<T>::subspan<Offset, Count>(): Offset out of range" ); |
496 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count == dynamic_extent || _Count <= size() - _Offset, |
497 | "span<T>::subspan<Offset, Count>(): Offset + Count out of range" ); |
498 | return span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; |
499 | } |
500 | |
501 | constexpr span<element_type, dynamic_extent> _LIBCPP_HIDE_FROM_ABI |
502 | subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept { |
503 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__offset <= size(), "span<T>::subspan(offset, count): offset out of range" ); |
504 | if (__count == dynamic_extent) |
505 | return {data() + __offset, size() - __offset}; |
506 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( |
507 | __count <= size() - __offset, "span<T>::subspan(offset, count): offset + count out of range" ); |
508 | return {data() + __offset, __count}; |
509 | } |
510 | |
511 | _LIBCPP_HIDE_FROM_ABI constexpr size_type size() const noexcept { return __size_; } |
512 | _LIBCPP_HIDE_FROM_ABI constexpr size_type size_bytes() const noexcept { return __size_ * sizeof(element_type); } |
513 | [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const noexcept { return __size_ == 0; } |
514 | |
515 | _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](size_type __idx) const noexcept { |
516 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__idx < size(), "span<T>::operator[](index): index out of range" ); |
517 | return __data_[__idx]; |
518 | } |
519 | |
520 | # if _LIBCPP_STD_VER >= 26 |
521 | _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const { |
522 | if (__index >= size()) |
523 | std::__throw_out_of_range("span" ); |
524 | return __data_[__index]; |
525 | } |
526 | # endif |
527 | |
528 | _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept { |
529 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::front() on empty span" ); |
530 | return __data_[0]; |
531 | } |
532 | |
533 | _LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept { |
534 | _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::back() on empty span" ); |
535 | return __data_[size() - 1]; |
536 | } |
537 | |
538 | _LIBCPP_HIDE_FROM_ABI constexpr pointer data() const noexcept { return __data_; } |
539 | |
540 | // [span.iter], span iterator support |
541 | _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() const noexcept { |
542 | # ifdef _LIBCPP_ABI_BOUNDED_ITERATORS |
543 | return std::__make_bounded_iter(data(), data(), data() + size()); |
544 | # else |
545 | return iterator(data()); |
546 | # endif |
547 | } |
548 | _LIBCPP_HIDE_FROM_ABI constexpr iterator end() const noexcept { |
549 | # ifdef _LIBCPP_ABI_BOUNDED_ITERATORS |
550 | return std::__make_bounded_iter(data() + size(), data(), data() + size()); |
551 | # else |
552 | return iterator(data() + size()); |
553 | # endif |
554 | } |
555 | _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } |
556 | _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } |
557 | |
558 | _LIBCPP_HIDE_FROM_ABI span<const byte, dynamic_extent> __as_bytes() const noexcept { |
559 | return {reinterpret_cast<const byte*>(data()), size_bytes()}; |
560 | } |
561 | |
562 | _LIBCPP_HIDE_FROM_ABI span<byte, dynamic_extent> __as_writable_bytes() const noexcept { |
563 | return {reinterpret_cast<byte*>(data()), size_bytes()}; |
564 | } |
565 | |
566 | private: |
567 | pointer __data_; |
568 | size_type __size_; |
569 | }; |
570 | |
571 | template <class _Tp, size_t _Extent> |
572 | inline constexpr bool ranges::enable_borrowed_range<span<_Tp, _Extent> > = true; |
573 | |
574 | template <class _ElementType, size_t _Extent> |
575 | inline constexpr bool ranges::enable_view<span<_ElementType, _Extent>> = true; |
576 | |
577 | // as_bytes & as_writable_bytes |
578 | template <class _Tp, size_t _Extent> |
579 | _LIBCPP_HIDE_FROM_ABI auto as_bytes(span<_Tp, _Extent> __s) noexcept { |
580 | return __s.__as_bytes(); |
581 | } |
582 | |
583 | template <class _Tp, size_t _Extent> |
584 | requires(!is_const_v<_Tp>) |
585 | _LIBCPP_HIDE_FROM_ABI auto as_writable_bytes(span<_Tp, _Extent> __s) noexcept { |
586 | return __s.__as_writable_bytes(); |
587 | } |
588 | |
589 | # if _LIBCPP_STD_VER >= 26 |
590 | template <class _Tp> |
591 | concept __integral_constant_like = |
592 | is_integral_v<decltype(_Tp::value)> && !is_same_v<bool, remove_const_t<decltype(_Tp::value)>> && |
593 | convertible_to<_Tp, decltype(_Tp::value)> && equality_comparable_with<_Tp, decltype(_Tp::value)> && |
594 | bool_constant<_Tp() == _Tp::value>::value && |
595 | bool_constant<static_cast<decltype(_Tp::value)>(_Tp()) == _Tp::value>::value; |
596 | |
597 | template <class _Tp> |
598 | inline constexpr size_t __maybe_static_ext = dynamic_extent; |
599 | |
600 | template <__integral_constant_like _Tp> |
601 | inline constexpr size_t __maybe_static_ext<_Tp> = {_Tp::value}; |
602 | |
603 | template <contiguous_iterator _It, class _EndOrSize> |
604 | span(_It, _EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>, __maybe_static_ext<_EndOrSize>>; |
605 | # else |
606 | template <contiguous_iterator _It, class _EndOrSize> |
607 | span(_It, _EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>; |
608 | # endif |
609 | |
610 | template <class _Tp, size_t _Sz> |
611 | span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>; |
612 | |
613 | template <class _Tp, size_t _Sz> |
614 | span(array<_Tp, _Sz>&) -> span<_Tp, _Sz>; |
615 | |
616 | template <class _Tp, size_t _Sz> |
617 | span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>; |
618 | |
619 | template <ranges::contiguous_range _Range> |
620 | span(_Range&&) -> span<remove_reference_t<ranges::range_reference_t<_Range>>>; |
621 | |
622 | #endif // _LIBCPP_STD_VER >= 20 |
623 | |
624 | _LIBCPP_END_NAMESPACE_STD |
625 | |
626 | _LIBCPP_POP_MACROS |
627 | |
628 | #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 |
629 | # include <array> |
630 | # include <concepts> |
631 | # include <functional> |
632 | # include <iterator> |
633 | # include <type_traits> |
634 | #endif |
635 | |
636 | #endif // _LIBCPP_SPAN |
637 | |