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