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