1// -*- C++ -*- 2//===------------------------------ span ---------------------------------===// 3// 4// The LLVM Compiler Infrastructure 5// 6// This file is dual licensed under the MIT and the University of Illinois Open 7// Source Licenses. See LICENSE.TXT for details. 8// 9//===---------------------------------------------------------------------===// 10 11#ifndef _LIBCPP_SPAN 12#define _LIBCPP_SPAN 13 14/* 15 span synopsis 16 17namespace std { 18 19// constants 20inline constexpr ptrdiff_t dynamic_extent = -1; 21 22// [views.span], class template span 23template <class ElementType, ptrdiff_t Extent = dynamic_extent> 24 class span; 25 26// [span.comparison], span comparison operators 27template <class T, ptrdiff_t X, class U, ptrdiff_t Y> 28 constexpr bool operator==(span<T, X> l, span<U, Y> r); 29template <class T, ptrdiff_t X, class U, ptrdiff_t Y> 30 constexpr bool operator!=(span<T, X> l, span<U, Y> r); 31template <class T, ptrdiff_t X, class U, ptrdiff_t Y> 32 constexpr bool operator<(span<T, X> l, span<U, Y> r); 33template <class T, ptrdiff_t X, class U, ptrdiff_t Y> 34 constexpr bool operator<=(span<T, X> l, span<U, Y> r); 35template <class T, ptrdiff_t X, class U, ptrdiff_t Y> 36 constexpr bool operator>(span<T, X> l, span<U, Y> r); 37template <class T, ptrdiff_t X, class U, ptrdiff_t Y> 38 constexpr bool operator>=(span<T, X> l, span<U, Y> r); 39 40// [span.objectrep], views of object representation 41template <class ElementType, ptrdiff_t Extent> 42 span<const byte, ((Extent == dynamic_extent) ? dynamic_extent : 43 (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept; 44 45template <class ElementType, ptrdiff_t Extent> 46 span< byte, ((Extent == dynamic_extent) ? dynamic_extent : 47 (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept; 48 49 50namespace std { 51template <class ElementType, ptrdiff_t Extent = dynamic_extent> 52class span { 53public: 54 // constants and types 55 using element_type = ElementType; 56 using value_type = remove_cv_t<ElementType>; 57 using index_type = ptrdiff_t; 58 using difference_type = ptrdiff_t; 59 using pointer = element_type*; 60 using reference = element_type&; 61 using iterator = implementation-defined; 62 using const_iterator = implementation-defined; 63 using reverse_iterator = std::reverse_iterator<iterator>; 64 using const_reverse_iterator = std::reverse_iterator<const_iterator>; 65 static constexpr index_type extent = Extent; 66 67 // [span.cons], span constructors, copy, assignment, and destructor 68 constexpr span() noexcept; 69 constexpr span(pointer ptr, index_type count); 70 constexpr span(pointer firstElem, pointer lastElem); 71 template <size_t N> 72 constexpr span(element_type (&arr)[N]) noexcept; 73 template <size_t N> 74 constexpr span(array<value_type, N>& arr) noexcept; 75 template <size_t N> 76 constexpr span(const array<value_type, N>& arr) noexcept; 77 template <class Container> 78 constexpr span(Container& cont); 79 template <class Container> 80 constexpr span(const Container& cont); 81 constexpr span(const span& other) noexcept = default; 82 template <class OtherElementType, ptrdiff_t OtherExtent> 83 constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept; 84 ~span() noexcept = default; 85 constexpr span& operator=(const span& other) noexcept = default; 86 87 // [span.sub], span subviews 88 template <ptrdiff_t Count> 89 constexpr span<element_type, Count> first() const; 90 template <ptrdiff_t Count> 91 constexpr span<element_type, Count> last() const; 92 template <ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent> 93 constexpr span<element_type, see below> subspan() const; 94 95 constexpr span<element_type, dynamic_extent> first(index_type count) const; 96 constexpr span<element_type, dynamic_extent> last(index_type count) const; 97 constexpr span<element_type, dynamic_extent> subspan(index_type offset, index_type count = dynamic_extent) const; 98 99 // [span.obs], span observers 100 constexpr index_type size() const noexcept; 101 constexpr index_type size_bytes() const noexcept; 102 constexpr bool empty() const noexcept; 103 104 // [span.elem], span element access 105 constexpr reference operator[](index_type idx) const; 106 constexpr reference operator()(index_type idx) const; 107 constexpr pointer data() const noexcept; 108 109 // [span.iterators], span iterator support 110 constexpr iterator begin() const noexcept; 111 constexpr iterator end() const noexcept; 112 constexpr const_iterator cbegin() const noexcept; 113 constexpr const_iterator cend() const noexcept; 114 constexpr reverse_iterator rbegin() const noexcept; 115 constexpr reverse_iterator rend() const noexcept; 116 constexpr const_reverse_iterator crbegin() const noexcept; 117 constexpr const_reverse_iterator crend() const noexcept; 118 119private: 120 pointer data_; // exposition only 121 index_type size_; // exposition only 122}; 123 124template<class T, size_t N> 125 span(T (&)[N]) -> span<T, N>; 126 127template<class T, size_t N> 128 span(array<T, N>&) -> span<T, N>; 129 130template<class T, size_t N> 131 span(const array<T, N>&) -> span<const T, N>; 132 133template<class Container> 134 span(Container&) -> span<typename Container::value_type>; 135 136template<class Container> 137 span(const Container&) -> span<const typename Container::value_type>; 138 139} // namespace std 140 141*/ 142 143#include <__config> 144#include <cstddef> // for ptrdiff_t 145#include <iterator> // for iterators 146#include <array> // for array 147#include <type_traits> // for remove_cv, etc 148#include <cstddef> // for byte 149 150#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 151#pragma GCC system_header 152#endif 153 154_LIBCPP_BEGIN_NAMESPACE_STD 155 156#if _LIBCPP_STD_VER > 17 157 158inline constexpr ptrdiff_t dynamic_extent = -1; 159template <typename _Tp, ptrdiff_t _Extent = dynamic_extent> class span; 160 161 162template <class _Tp> 163struct __is_span_impl : public false_type {}; 164 165template <class _Tp, ptrdiff_t _Extent> 166struct __is_span_impl<span<_Tp, _Extent>> : public true_type {}; 167 168template <class _Tp> 169struct __is_span : public __is_span_impl<remove_cv_t<_Tp>> {}; 170 171template <class _Tp> 172struct __is_std_array_impl : public false_type {}; 173 174template <class _Tp, size_t _Sz> 175struct __is_std_array_impl<array<_Tp, _Sz>> : public true_type {}; 176 177template <class _Tp> 178struct __is_std_array : public __is_std_array_impl<remove_cv_t<_Tp>> {}; 179 180template <class _Tp, class _ElementType, class = void> 181struct __is_span_compatible_container : public false_type {}; 182 183template <class _Tp, class _ElementType> 184struct __is_span_compatible_container<_Tp, _ElementType, 185 void_t< 186 // is not a specialization of span 187 typename enable_if<!__is_span<_Tp>::value, nullptr_t>::type, 188 // is not a specialization of array 189 typename enable_if<!__is_std_array<_Tp>::value, nullptr_t>::type, 190 // is_array_v<Container> is false, 191 typename enable_if<!is_array_v<_Tp>, nullptr_t>::type, 192 // data(cont) and size(cont) are well formed 193 decltype(data(declval<_Tp>())), 194 decltype(size(declval<_Tp>())), 195 // remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[] 196 typename enable_if< 197 is_convertible_v<remove_pointer_t<decltype(data(declval<_Tp &>()))>(*)[], 198 _ElementType(*)[]>, 199 nullptr_t>::type 200 >> 201 : public true_type {}; 202 203 204template <typename _Tp, ptrdiff_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 index_type = ptrdiff_t; 211 using difference_type = ptrdiff_t; 212 using pointer = _Tp *; 213 using const_pointer = const _Tp *; // not in standard 214 using reference = _Tp &; 215 using const_reference = const _Tp &; // not in standard 216 using iterator = __wrap_iter<pointer>; 217 using const_iterator = __wrap_iter<const_pointer>; 218 using reverse_iterator = _VSTD::reverse_iterator<iterator>; 219 using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>; 220 221 static constexpr index_type extent = _Extent; 222 static_assert (_Extent >= 0, "Can't have a span with an extent < 0"); 223 224// [span.cons], span constructors, copy, assignment, and destructor 225 _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr} 226 { static_assert(_Extent == 0, "Can't default construct a statically sized span with size > 0"); } 227 228 constexpr span (const span&) noexcept = default; 229 constexpr span& operator=(const span&) noexcept = default; 230 231 _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr} 232 { (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); } 233 _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f} 234 { (void)__l; _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); } 235 236 _LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent]) noexcept : __data{__arr} {} 237 _LIBCPP_INLINE_VISIBILITY constexpr span( array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {} 238 _LIBCPP_INLINE_VISIBILITY constexpr span(const array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {} 239 240 template <class _Container> 241 inline _LIBCPP_INLINE_VISIBILITY 242 constexpr span( _Container& __c, 243 enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr) 244 : __data{_VSTD::data(__c)} 245 { _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (container))"); } 246 247 template <class _Container> 248 inline _LIBCPP_INLINE_VISIBILITY 249 constexpr span(const _Container& __c, 250 enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr) 251 : __data{_VSTD::data(__c)} 252 { _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (const container)"); } 253 254 template <class _OtherElementType> 255 inline _LIBCPP_INLINE_VISIBILITY 256 constexpr span(const span<_OtherElementType, _Extent>& __other, 257 enable_if_t< 258 is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, 259 nullptr_t> = nullptr) 260 : __data{__other.data()} {} 261 262 template <class _OtherElementType> 263 inline _LIBCPP_INLINE_VISIBILITY 264 constexpr span(const span<_OtherElementType, dynamic_extent>& __other, 265 enable_if_t< 266 is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, 267 nullptr_t> = nullptr) noexcept 268 : __data{__other.data()} { _LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); } 269 270 271// ~span() noexcept = default; 272 273 template <ptrdiff_t _Count> 274 inline _LIBCPP_INLINE_VISIBILITY 275 constexpr span<element_type, _Count> first() const noexcept 276 { 277 static_assert(_Count >= 0, "Count must be >= 0 in span::first()"); 278 static_assert(_Count <= _Extent, "Count out of range in span::first()"); 279 return {data(), _Count}; 280 } 281 282 template <ptrdiff_t _Count> 283 inline _LIBCPP_INLINE_VISIBILITY 284 constexpr span<element_type, _Count> last() const noexcept 285 { 286 static_assert(_Count >= 0, "Count must be >= 0 in span::last()"); 287 static_assert(_Count <= _Extent, "Count out of range in span::last()"); 288 return {data() + size() - _Count, _Count}; 289 } 290 291 _LIBCPP_INLINE_VISIBILITY 292 constexpr span<element_type, dynamic_extent> first(index_type __count) const noexcept 293 { 294 _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::first(count)"); 295 return {data(), __count}; 296 } 297 298 _LIBCPP_INLINE_VISIBILITY 299 constexpr span<element_type, dynamic_extent> last(index_type __count) const noexcept 300 { 301 _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::last(count)"); 302 return {data() + size() - __count, __count}; 303 } 304 305 template <ptrdiff_t _Offset, ptrdiff_t _Count = dynamic_extent> 306 inline _LIBCPP_INLINE_VISIBILITY 307 constexpr auto subspan() const noexcept 308 -> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset> 309 { 310 _LIBCPP_ASSERT(_Offset >= 0 && _Offset <= size(), "Offset out of range in span::subspan()"); 311 return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; 312 } 313 314 315 inline _LIBCPP_INLINE_VISIBILITY 316 constexpr span<element_type, dynamic_extent> 317 subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept 318 { 319 _LIBCPP_ASSERT( __offset >= 0 && __offset <= size(), "Offset out of range in span::subspan(offset, count)"); 320 _LIBCPP_ASSERT((__count >= 0 && __count <= size()) || __count == dynamic_extent, "Count out of range in span::subspan(offset, count)"); 321 if (__count == dynamic_extent) 322 return {data() + __offset, size() - __offset}; 323 _LIBCPP_ASSERT(__offset + __count <= size(), "count + offset out of range in span::subspan(offset, count)"); 324 return {data() + __offset, __count}; 325 } 326 327 _LIBCPP_INLINE_VISIBILITY constexpr index_type size() const noexcept { return _Extent; } 328 _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return _Extent * sizeof(element_type); } 329 _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return _Extent == 0; } 330 331 _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept 332 { 333 _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T,N>[] index out of bounds"); 334 return __data[__idx]; 335 } 336 337 _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept 338 { 339 _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T,N>() index out of bounds"); 340 return __data[__idx]; 341 } 342 343 _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } 344 345// [span.iter], span iterator support 346 _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); } 347 _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); } 348 _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); } 349 _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); } 350 _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } 351 _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } 352 _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); } 353 _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); } 354 355 _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept 356 { 357 pointer __p = __data; 358 __data = __other.__data; 359 __other.__data = __p; 360 } 361 362 _LIBCPP_INLINE_VISIBILITY span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept 363 { return {reinterpret_cast<const byte *>(data()), size_bytes()}; } 364 365 _LIBCPP_INLINE_VISIBILITY span<byte, _Extent * sizeof(element_type)> __as_writeable_bytes() const noexcept 366 { return {reinterpret_cast<byte *>(data()), size_bytes()}; } 367 368private: 369 pointer __data; 370 371}; 372 373 374template <typename _Tp> 375class _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> { 376private: 377 378public: 379// constants and types 380 using element_type = _Tp; 381 using value_type = remove_cv_t<_Tp>; 382 using index_type = ptrdiff_t; 383 using difference_type = ptrdiff_t; 384 using pointer = _Tp *; 385 using const_pointer = const _Tp *; // not in standard 386 using reference = _Tp &; 387 using const_reference = const _Tp &; // not in standard 388 using iterator = __wrap_iter<pointer>; 389 using const_iterator = __wrap_iter<const_pointer>; 390 using reverse_iterator = _VSTD::reverse_iterator<iterator>; 391 using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>; 392 393 static constexpr index_type extent = dynamic_extent; 394 395// [span.cons], span constructors, copy, assignment, and destructor 396 _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} {} 397 398 constexpr span (const span&) noexcept = default; 399 constexpr span& operator=(const span&) noexcept = default; 400 401 _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr}, __size{__count} {} 402 _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{distance(__f, __l)} {} 403 404 template <size_t _Sz> 405 inline _LIBCPP_INLINE_VISIBILITY 406 constexpr span(element_type (&__arr)[_Sz]) noexcept : __data{__arr}, __size{_Sz} {} 407 408 template <size_t _Sz> 409 inline _LIBCPP_INLINE_VISIBILITY 410 constexpr span(array<value_type, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {} 411 412 template <size_t _Sz> 413 inline _LIBCPP_INLINE_VISIBILITY 414 constexpr span(const array<value_type, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {} 415 416 template <class _Container> 417 inline _LIBCPP_INLINE_VISIBILITY 418 constexpr span( _Container& __c, 419 enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr) 420 : __data{_VSTD::data(__c)}, __size{(index_type) _VSTD::size(__c)} {} 421 422 template <class _Container> 423 inline _LIBCPP_INLINE_VISIBILITY 424 constexpr span(const _Container& __c, 425 enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr) 426 : __data{_VSTD::data(__c)}, __size{(index_type) _VSTD::size(__c)} {} 427 428 429 template <class _OtherElementType, ptrdiff_t _OtherExtent> 430 inline _LIBCPP_INLINE_VISIBILITY 431 constexpr span(const span<_OtherElementType, _OtherExtent>& __other, 432 enable_if_t< 433 is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, 434 nullptr_t> = nullptr) noexcept 435 : __data{__other.data()}, __size{__other.size()} {} 436 437// ~span() noexcept = default; 438 439 template <ptrdiff_t _Count> 440 inline _LIBCPP_INLINE_VISIBILITY 441 constexpr span<element_type, _Count> first() const noexcept 442 { 443 static_assert(_Count >= 0); 444 _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()"); 445 return {data(), _Count}; 446 } 447 448 template <ptrdiff_t _Count> 449 inline _LIBCPP_INLINE_VISIBILITY 450 constexpr span<element_type, _Count> last() const noexcept 451 { 452 static_assert(_Count >= 0); 453 _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()"); 454 return {data() + size() - _Count, _Count}; 455 } 456 457 _LIBCPP_INLINE_VISIBILITY 458 constexpr span<element_type, dynamic_extent> first(index_type __count) const noexcept 459 { 460 _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::first(count)"); 461 return {data(), __count}; 462 } 463 464 _LIBCPP_INLINE_VISIBILITY 465 constexpr span<element_type, dynamic_extent> last (index_type __count) const noexcept 466 { 467 _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::last(count)"); 468 return {data() + size() - __count, __count}; 469 } 470 471 template <ptrdiff_t _Offset, ptrdiff_t _Count = dynamic_extent> 472 inline _LIBCPP_INLINE_VISIBILITY 473 constexpr span<_Tp, dynamic_extent> subspan() const noexcept 474 { 475 _LIBCPP_ASSERT(_Offset >= 0 && _Offset <= size(), "Offset out of range in span::subspan()"); 476 _LIBCPP_ASSERT(_Count == dynamic_extent || _Offset + _Count <= size(), "Count out of range in span::subspan()"); 477 return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; 478 } 479 480 constexpr span<element_type, dynamic_extent> 481 inline _LIBCPP_INLINE_VISIBILITY 482 subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept 483 { 484 _LIBCPP_ASSERT( __offset >= 0 && __offset <= size(), "Offset out of range in span::subspan(offset, count)"); 485 _LIBCPP_ASSERT((__count >= 0 && __count <= size()) || __count == dynamic_extent, "count out of range in span::subspan(offset, count)"); 486 if (__count == dynamic_extent) 487 return {data() + __offset, size() - __offset}; 488 _LIBCPP_ASSERT(__offset + __count <= size(), "Offset + count out of range in span::subspan(offset, count)"); 489 return {data() + __offset, __count}; 490 } 491 492 _LIBCPP_INLINE_VISIBILITY constexpr index_type size() const noexcept { return __size; } 493 _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return __size * sizeof(element_type); } 494 _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return __size == 0; } 495 496 _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept 497 { 498 _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T>[] index out of bounds"); 499 return __data[__idx]; 500 } 501 502 _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept 503 { 504 _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T>() index out of bounds"); 505 return __data[__idx]; 506 } 507 508 _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } 509 510// [span.iter], span iterator support 511 _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); } 512 _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); } 513 _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); } 514 _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); } 515 _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } 516 _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } 517 _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); } 518 _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); } 519 520 _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept 521 { 522 pointer __p = __data; 523 __data = __other.__data; 524 __other.__data = __p; 525 526 index_type __sz = __size; 527 __size = __other.__size; 528 __other.__size = __sz; 529 } 530 531 _LIBCPP_INLINE_VISIBILITY span<const byte, dynamic_extent> __as_bytes() const noexcept 532 { return {reinterpret_cast<const byte *>(data()), size_bytes()}; } 533 534 _LIBCPP_INLINE_VISIBILITY span<byte, dynamic_extent> __as_writeable_bytes() const noexcept 535 { return {reinterpret_cast<byte *>(data()), size_bytes()}; } 536 537private: 538 pointer __data; 539 index_type __size; 540}; 541 542template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2> 543 constexpr bool 544 operator==(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) 545 { return equal(__lhs.begin(), __lhs.end(), __rhs.begin(), __rhs.end()); } 546 547template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2> 548 constexpr bool 549 operator!=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) 550 { return !(__rhs == __lhs); } 551 552template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2> 553 constexpr bool 554 operator< (const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) 555 { return lexicographical_compare (__lhs.begin(), __lhs.end(), __rhs.begin(), __rhs.end()); } 556 557template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2> 558 constexpr bool 559 operator<=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) 560 { return !(__rhs < __lhs); } 561 562template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2> 563 constexpr bool 564 operator> (const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) 565 { return __rhs < __lhs; } 566 567template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2> 568 constexpr bool 569 operator>=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) 570 { return !(__lhs < __rhs); } 571 572// as_bytes & as_writeable_bytes 573template <class _Tp, ptrdiff_t _Extent> 574 auto as_bytes(span<_Tp, _Extent> __s) noexcept 575 -> decltype(__s.__as_bytes()) 576 { return __s.__as_bytes(); } 577 578template <class _Tp, ptrdiff_t _Extent> 579 auto as_writeable_bytes(span<_Tp, _Extent> __s) noexcept 580 -> typename enable_if<!is_const_v<_Tp>, decltype(__s.__as_writeable_bytes())>::type 581 { return __s.__as_writeable_bytes(); } 582 583template <class _Tp, ptrdiff_t _Extent> 584 constexpr void swap(span<_Tp, _Extent> &__lhs, span<_Tp, _Extent> &__rhs) noexcept 585 { __lhs.swap(__rhs); } 586 587 588// Deduction guides 589template<class _Tp, size_t _Sz> 590 span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>; 591 592template<class _Tp, size_t _Sz> 593 span(array<_Tp, _Sz>&) -> span<_Tp, _Sz>; 594 595template<class _Tp, size_t _Sz> 596 span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>; 597 598template<class _Container> 599 span(_Container&) -> span<typename _Container::value_type>; 600 601template<class _Container> 602 span(const _Container&) -> span<const typename _Container::value_type>; 603 604#endif // _LIBCPP_STD_VER > 17 605 606_LIBCPP_END_NAMESPACE_STD 607 608#endif // _LIBCPP_SPAN 609