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