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