xref: /llvm-project/libcxx/include/span (revision b9a2658a3e8bd13b0f9e7a8a440832a95b377216)
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
16namespace std {
17
18// constants
19inline constexpr size_t dynamic_extent = numeric_limits<size_t>::max();
20
21template<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
30template<class T>
31  constexpr size_t maybe-static-ext = dynamic_extent;        // exposition only, since C++26
32template<integral-constant-like T>
33  constexpr size_t maybe-static-ext<T> = {T::value};
34
35// [views.span], class template span
36template <class ElementType, size_t Extent = dynamic_extent>
37    class span;
38
39template<class ElementType, size_t Extent>
40  inline constexpr bool ranges::enable_view<span<ElementType, Extent>> = true;
41
42template<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
46template <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
50template <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
55template <class ElementType, size_t Extent = dynamic_extent>
56class span {
57public:
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
121private:
122    pointer data_;    // exposition only
123    size_type size_;  // exposition only
124};
125
126template<class It, class EndOrSize>
127    span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>;                             // until C++26
128template<class It, class EndOrSize>
129    span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<It>>, maybe-static-ext<EndOrSize>>; // since C++26
130
131template<class T, size_t N>
132    span(T (&)[N]) -> span<T, N>;
133
134template<class T, size_t N>
135    span(array<T, N>&) -> span<T, N>;
136
137template<class T, size_t N>
138    span(const array<T, N>&) -> span<const T, N>;
139
140template<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/span>
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
205template <class _Tp>
206struct __is_std_span : false_type {};
207
208template <class _Tp, size_t _Sz>
209struct __is_std_span<span<_Tp, _Sz>> : true_type {};
210
211template <class _Range, class _ElementType>
212concept __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
221template <class _From, class _To>
222concept __span_array_convertible = is_convertible_v<_From (*)[], _To (*)[]>;
223
224template <class _It, class _Tp>
225concept __span_compatible_iterator =
226    contiguous_iterator<_It> && __span_array_convertible<remove_reference_t<iter_reference_t<_It>>, _Tp>;
227
228template <class _Sentinel, class _It>
229concept __span_compatible_sentinel_for = sized_sentinel_for<_Sentinel, _It> && !is_convertible_v<_Sentinel, size_t>;
230
231template <typename _Tp, size_t _Extent>
232class _LIBCPP_TEMPLATE_VIS span {
233public:
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
410private:
411  pointer __data_;
412};
413
414template <typename _Tp>
415class _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> {
416public:
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
575private:
576  pointer __data_;
577  size_type __size_;
578};
579
580template <class _Tp, size_t _Extent>
581inline constexpr bool ranges::enable_borrowed_range<span<_Tp, _Extent> > = true;
582
583template <class _ElementType, size_t _Extent>
584inline constexpr bool ranges::enable_view<span<_ElementType, _Extent>> = true;
585
586//  as_bytes & as_writable_bytes
587template <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
592template <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
599template <class _Tp>
600concept __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
606template <class _Tp>
607inline constexpr size_t __maybe_static_ext = dynamic_extent;
608
609template <__integral_constant_like _Tp>
610inline constexpr size_t __maybe_static_ext<_Tp> = {_Tp::value};
611
612template <contiguous_iterator _It, class _EndOrSize>
613span(_It, _EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>, __maybe_static_ext<_EndOrSize>>;
614#    else
615template <contiguous_iterator _It, class _EndOrSize>
616span(_It, _EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>;
617#    endif
618
619template <class _Tp, size_t _Sz>
620span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>;
621
622template <class _Tp, size_t _Sz>
623span(array<_Tp, _Sz>&) -> span<_Tp, _Sz>;
624
625template <class _Tp, size_t _Sz>
626span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>;
627
628template <ranges::contiguous_range _Range>
629span(_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