14ba319b5SDimitry Andric// -*- C++ -*- 24ba319b5SDimitry Andric//===------------------------------ span ---------------------------------===// 34ba319b5SDimitry Andric// 44ba319b5SDimitry Andric// The LLVM Compiler Infrastructure 54ba319b5SDimitry Andric// 64ba319b5SDimitry Andric// This file is dual licensed under the MIT and the University of Illinois Open 74ba319b5SDimitry Andric// Source Licenses. See LICENSE.TXT for details. 84ba319b5SDimitry Andric// 94ba319b5SDimitry Andric//===---------------------------------------------------------------------===// 104ba319b5SDimitry Andric 114ba319b5SDimitry Andric#ifndef _LIBCPP_SPAN 124ba319b5SDimitry Andric#define _LIBCPP_SPAN 134ba319b5SDimitry Andric 144ba319b5SDimitry Andric/* 154ba319b5SDimitry Andric span synopsis 164ba319b5SDimitry Andric 174ba319b5SDimitry Andricnamespace std { 184ba319b5SDimitry Andric 194ba319b5SDimitry Andric// constants 204ba319b5SDimitry Andricinline constexpr ptrdiff_t dynamic_extent = -1; 214ba319b5SDimitry Andric 224ba319b5SDimitry Andric// [views.span], class template span 234ba319b5SDimitry Andrictemplate <class ElementType, ptrdiff_t Extent = dynamic_extent> 244ba319b5SDimitry Andric class span; 254ba319b5SDimitry Andric 264ba319b5SDimitry Andric// [span.objectrep], views of object representation 274ba319b5SDimitry Andrictemplate <class ElementType, ptrdiff_t Extent> 284ba319b5SDimitry Andric span<const byte, ((Extent == dynamic_extent) ? dynamic_extent : 294ba319b5SDimitry Andric (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept; 304ba319b5SDimitry Andric 314ba319b5SDimitry Andrictemplate <class ElementType, ptrdiff_t Extent> 324ba319b5SDimitry Andric span< byte, ((Extent == dynamic_extent) ? dynamic_extent : 334ba319b5SDimitry Andric (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept; 344ba319b5SDimitry Andric 354ba319b5SDimitry Andric 364ba319b5SDimitry Andricnamespace std { 374ba319b5SDimitry Andrictemplate <class ElementType, ptrdiff_t Extent = dynamic_extent> 384ba319b5SDimitry Andricclass span { 394ba319b5SDimitry Andricpublic: 404ba319b5SDimitry Andric // constants and types 414ba319b5SDimitry Andric using element_type = ElementType; 424ba319b5SDimitry Andric using value_type = remove_cv_t<ElementType>; 434ba319b5SDimitry Andric using index_type = ptrdiff_t; 444ba319b5SDimitry Andric using difference_type = ptrdiff_t; 454ba319b5SDimitry Andric using pointer = element_type*; 464ba319b5SDimitry Andric using reference = element_type&; 474ba319b5SDimitry Andric using iterator = implementation-defined; 484ba319b5SDimitry Andric using const_iterator = implementation-defined; 494ba319b5SDimitry Andric using reverse_iterator = std::reverse_iterator<iterator>; 504ba319b5SDimitry Andric using const_reverse_iterator = std::reverse_iterator<const_iterator>; 514ba319b5SDimitry Andric static constexpr index_type extent = Extent; 524ba319b5SDimitry Andric 534ba319b5SDimitry Andric // [span.cons], span constructors, copy, assignment, and destructor 544ba319b5SDimitry Andric constexpr span() noexcept; 554ba319b5SDimitry Andric constexpr span(pointer ptr, index_type count); 564ba319b5SDimitry Andric constexpr span(pointer firstElem, pointer lastElem); 574ba319b5SDimitry Andric template <size_t N> 584ba319b5SDimitry Andric constexpr span(element_type (&arr)[N]) noexcept; 594ba319b5SDimitry Andric template <size_t N> 604ba319b5SDimitry Andric constexpr span(array<value_type, N>& arr) noexcept; 614ba319b5SDimitry Andric template <size_t N> 624ba319b5SDimitry Andric constexpr span(const array<value_type, N>& arr) noexcept; 634ba319b5SDimitry Andric template <class Container> 644ba319b5SDimitry Andric constexpr span(Container& cont); 654ba319b5SDimitry Andric template <class Container> 664ba319b5SDimitry Andric constexpr span(const Container& cont); 674ba319b5SDimitry Andric constexpr span(const span& other) noexcept = default; 684ba319b5SDimitry Andric template <class OtherElementType, ptrdiff_t OtherExtent> 694ba319b5SDimitry Andric constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept; 704ba319b5SDimitry Andric ~span() noexcept = default; 714ba319b5SDimitry Andric constexpr span& operator=(const span& other) noexcept = default; 724ba319b5SDimitry Andric 734ba319b5SDimitry Andric // [span.sub], span subviews 744ba319b5SDimitry Andric template <ptrdiff_t Count> 754ba319b5SDimitry Andric constexpr span<element_type, Count> first() const; 764ba319b5SDimitry Andric template <ptrdiff_t Count> 774ba319b5SDimitry Andric constexpr span<element_type, Count> last() const; 784ba319b5SDimitry Andric template <ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent> 794ba319b5SDimitry Andric constexpr span<element_type, see below> subspan() const; 804ba319b5SDimitry Andric 814ba319b5SDimitry Andric constexpr span<element_type, dynamic_extent> first(index_type count) const; 824ba319b5SDimitry Andric constexpr span<element_type, dynamic_extent> last(index_type count) const; 834ba319b5SDimitry Andric constexpr span<element_type, dynamic_extent> subspan(index_type offset, index_type count = dynamic_extent) const; 844ba319b5SDimitry Andric 854ba319b5SDimitry Andric // [span.obs], span observers 864ba319b5SDimitry Andric constexpr index_type size() const noexcept; 874ba319b5SDimitry Andric constexpr index_type size_bytes() const noexcept; 884ba319b5SDimitry Andric constexpr bool empty() const noexcept; 894ba319b5SDimitry Andric 904ba319b5SDimitry Andric // [span.elem], span element access 914ba319b5SDimitry Andric constexpr reference operator[](index_type idx) const; 924ba319b5SDimitry Andric constexpr reference operator()(index_type idx) const; 934ba319b5SDimitry Andric constexpr pointer data() const noexcept; 944ba319b5SDimitry Andric 954ba319b5SDimitry Andric // [span.iterators], span iterator support 964ba319b5SDimitry Andric constexpr iterator begin() const noexcept; 974ba319b5SDimitry Andric constexpr iterator end() const noexcept; 984ba319b5SDimitry Andric constexpr const_iterator cbegin() const noexcept; 994ba319b5SDimitry Andric constexpr const_iterator cend() const noexcept; 1004ba319b5SDimitry Andric constexpr reverse_iterator rbegin() const noexcept; 1014ba319b5SDimitry Andric constexpr reverse_iterator rend() const noexcept; 1024ba319b5SDimitry Andric constexpr const_reverse_iterator crbegin() const noexcept; 1034ba319b5SDimitry Andric constexpr const_reverse_iterator crend() const noexcept; 1044ba319b5SDimitry Andric 1054ba319b5SDimitry Andricprivate: 1064ba319b5SDimitry Andric pointer data_; // exposition only 1074ba319b5SDimitry Andric index_type size_; // exposition only 1084ba319b5SDimitry Andric}; 1094ba319b5SDimitry Andric 1104ba319b5SDimitry Andrictemplate<class T, size_t N> 1114ba319b5SDimitry Andric span(T (&)[N]) -> span<T, N>; 1124ba319b5SDimitry Andric 1134ba319b5SDimitry Andrictemplate<class T, size_t N> 1144ba319b5SDimitry Andric span(array<T, N>&) -> span<T, N>; 1154ba319b5SDimitry Andric 1164ba319b5SDimitry Andrictemplate<class T, size_t N> 1174ba319b5SDimitry Andric span(const array<T, N>&) -> span<const T, N>; 1184ba319b5SDimitry Andric 1194ba319b5SDimitry Andrictemplate<class Container> 1204ba319b5SDimitry Andric span(Container&) -> span<typename Container::value_type>; 1214ba319b5SDimitry Andric 1224ba319b5SDimitry Andrictemplate<class Container> 1234ba319b5SDimitry Andric span(const Container&) -> span<const typename Container::value_type>; 1244ba319b5SDimitry Andric 1254ba319b5SDimitry Andric} // namespace std 1264ba319b5SDimitry Andric 1274ba319b5SDimitry Andric*/ 1284ba319b5SDimitry Andric 1294ba319b5SDimitry Andric#include <__config> 1304ba319b5SDimitry Andric#include <cstddef> // for ptrdiff_t 1314ba319b5SDimitry Andric#include <iterator> // for iterators 1324ba319b5SDimitry Andric#include <array> // for array 1334ba319b5SDimitry Andric#include <type_traits> // for remove_cv, etc 1344ba319b5SDimitry Andric#include <cstddef> // for byte 1354ba319b5SDimitry Andric 1364ba319b5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 1374ba319b5SDimitry Andric#pragma GCC system_header 1384ba319b5SDimitry Andric#endif 1394ba319b5SDimitry Andric 1404ba319b5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 1414ba319b5SDimitry Andric 1424ba319b5SDimitry Andric#if _LIBCPP_STD_VER > 17 1434ba319b5SDimitry Andric 1444ba319b5SDimitry Andricinline constexpr ptrdiff_t dynamic_extent = -1; 1454ba319b5SDimitry Andrictemplate <typename _Tp, ptrdiff_t _Extent = dynamic_extent> class span; 1464ba319b5SDimitry Andric 1474ba319b5SDimitry Andric 1484ba319b5SDimitry Andrictemplate <class _Tp> 1494ba319b5SDimitry Andricstruct __is_span_impl : public false_type {}; 1504ba319b5SDimitry Andric 1514ba319b5SDimitry Andrictemplate <class _Tp, ptrdiff_t _Extent> 1524ba319b5SDimitry Andricstruct __is_span_impl<span<_Tp, _Extent>> : public true_type {}; 1534ba319b5SDimitry Andric 1544ba319b5SDimitry Andrictemplate <class _Tp> 1554ba319b5SDimitry Andricstruct __is_span : public __is_span_impl<remove_cv_t<_Tp>> {}; 1564ba319b5SDimitry Andric 1574ba319b5SDimitry Andrictemplate <class _Tp> 1584ba319b5SDimitry Andricstruct __is_std_array_impl : public false_type {}; 1594ba319b5SDimitry Andric 1604ba319b5SDimitry Andrictemplate <class _Tp, size_t _Sz> 1614ba319b5SDimitry Andricstruct __is_std_array_impl<array<_Tp, _Sz>> : public true_type {}; 1624ba319b5SDimitry Andric 1634ba319b5SDimitry Andrictemplate <class _Tp> 1644ba319b5SDimitry Andricstruct __is_std_array : public __is_std_array_impl<remove_cv_t<_Tp>> {}; 1654ba319b5SDimitry Andric 1664ba319b5SDimitry Andrictemplate <class _Tp, class _ElementType, class = void> 1674ba319b5SDimitry Andricstruct __is_span_compatible_container : public false_type {}; 1684ba319b5SDimitry Andric 1694ba319b5SDimitry Andrictemplate <class _Tp, class _ElementType> 1704ba319b5SDimitry Andricstruct __is_span_compatible_container<_Tp, _ElementType, 1714ba319b5SDimitry Andric void_t< 1724ba319b5SDimitry Andric // is not a specialization of span 1734ba319b5SDimitry Andric typename enable_if<!__is_span<_Tp>::value, nullptr_t>::type, 1744ba319b5SDimitry Andric // is not a specialization of array 1754ba319b5SDimitry Andric typename enable_if<!__is_std_array<_Tp>::value, nullptr_t>::type, 1764ba319b5SDimitry Andric // is_array_v<Container> is false, 1774ba319b5SDimitry Andric typename enable_if<!is_array_v<_Tp>, nullptr_t>::type, 1784ba319b5SDimitry Andric // data(cont) and size(cont) are well formed 1794ba319b5SDimitry Andric decltype(data(declval<_Tp>())), 1804ba319b5SDimitry Andric decltype(size(declval<_Tp>())), 1814ba319b5SDimitry Andric // remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[] 1824ba319b5SDimitry Andric typename enable_if< 1834ba319b5SDimitry Andric is_convertible_v<remove_pointer_t<decltype(data(declval<_Tp &>()))>(*)[], 1844ba319b5SDimitry Andric _ElementType(*)[]>, 1854ba319b5SDimitry Andric nullptr_t>::type 1864ba319b5SDimitry Andric >> 1874ba319b5SDimitry Andric : public true_type {}; 1884ba319b5SDimitry Andric 1894ba319b5SDimitry Andric 1904ba319b5SDimitry Andrictemplate <typename _Tp, ptrdiff_t _Extent> 1914ba319b5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS span { 1924ba319b5SDimitry Andricpublic: 1934ba319b5SDimitry Andric// constants and types 1944ba319b5SDimitry Andric using element_type = _Tp; 1954ba319b5SDimitry Andric using value_type = remove_cv_t<_Tp>; 1964ba319b5SDimitry Andric using index_type = ptrdiff_t; 1974ba319b5SDimitry Andric using difference_type = ptrdiff_t; 1984ba319b5SDimitry Andric using pointer = _Tp *; 1994ba319b5SDimitry Andric using const_pointer = const _Tp *; // not in standard 2004ba319b5SDimitry Andric using reference = _Tp &; 2014ba319b5SDimitry Andric using const_reference = const _Tp &; // not in standard 2024ba319b5SDimitry Andric using iterator = __wrap_iter<pointer>; 2034ba319b5SDimitry Andric using const_iterator = __wrap_iter<const_pointer>; 2044ba319b5SDimitry Andric using reverse_iterator = _VSTD::reverse_iterator<iterator>; 2054ba319b5SDimitry Andric using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>; 2064ba319b5SDimitry Andric 2074ba319b5SDimitry Andric static constexpr index_type extent = _Extent; 2084ba319b5SDimitry Andric static_assert (_Extent >= 0, "Can't have a span with an extent < 0"); 2094ba319b5SDimitry Andric 2104ba319b5SDimitry Andric// [span.cons], span constructors, copy, assignment, and destructor 2114ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr} 2124ba319b5SDimitry Andric { static_assert(_Extent == 0, "Can't default construct a statically sized span with size > 0"); } 2134ba319b5SDimitry Andric 2144ba319b5SDimitry Andric constexpr span (const span&) noexcept = default; 2154ba319b5SDimitry Andric constexpr span& operator=(const span&) noexcept = default; 2164ba319b5SDimitry Andric 2174ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr} 2184ba319b5SDimitry Andric { (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); } 2194ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f} 2204ba319b5SDimitry Andric { (void)__l; _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); } 2214ba319b5SDimitry Andric 2224ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent]) noexcept : __data{__arr} {} 2234ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span( array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {} 2244ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span(const array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {} 2254ba319b5SDimitry Andric 2264ba319b5SDimitry Andric template <class _Container> 2274ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 2284ba319b5SDimitry Andric constexpr span( _Container& __c, 2294ba319b5SDimitry Andric enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr) 2304ba319b5SDimitry Andric : __data{_VSTD::data(__c)} 231*b5893f02SDimitry Andric { _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (container)"); } 2324ba319b5SDimitry Andric 2334ba319b5SDimitry Andric template <class _Container> 2344ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 2354ba319b5SDimitry Andric constexpr span(const _Container& __c, 2364ba319b5SDimitry Andric enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr) 2374ba319b5SDimitry Andric : __data{_VSTD::data(__c)} 2384ba319b5SDimitry Andric { _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (const container)"); } 2394ba319b5SDimitry Andric 2404ba319b5SDimitry Andric template <class _OtherElementType> 2414ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 2424ba319b5SDimitry Andric constexpr span(const span<_OtherElementType, _Extent>& __other, 2434ba319b5SDimitry Andric enable_if_t< 2444ba319b5SDimitry Andric is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, 2454ba319b5SDimitry Andric nullptr_t> = nullptr) 2464ba319b5SDimitry Andric : __data{__other.data()} {} 2474ba319b5SDimitry Andric 2484ba319b5SDimitry Andric template <class _OtherElementType> 2494ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 2504ba319b5SDimitry Andric constexpr span(const span<_OtherElementType, dynamic_extent>& __other, 2514ba319b5SDimitry Andric enable_if_t< 2524ba319b5SDimitry Andric is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, 2534ba319b5SDimitry Andric nullptr_t> = nullptr) noexcept 2544ba319b5SDimitry Andric : __data{__other.data()} { _LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); } 2554ba319b5SDimitry Andric 2564ba319b5SDimitry Andric 2574ba319b5SDimitry Andric// ~span() noexcept = default; 2584ba319b5SDimitry Andric 2594ba319b5SDimitry Andric template <ptrdiff_t _Count> 2604ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 2614ba319b5SDimitry Andric constexpr span<element_type, _Count> first() const noexcept 2624ba319b5SDimitry Andric { 2634ba319b5SDimitry Andric static_assert(_Count >= 0, "Count must be >= 0 in span::first()"); 2644ba319b5SDimitry Andric static_assert(_Count <= _Extent, "Count out of range in span::first()"); 2654ba319b5SDimitry Andric return {data(), _Count}; 2664ba319b5SDimitry Andric } 2674ba319b5SDimitry Andric 2684ba319b5SDimitry Andric template <ptrdiff_t _Count> 2694ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 2704ba319b5SDimitry Andric constexpr span<element_type, _Count> last() const noexcept 2714ba319b5SDimitry Andric { 2724ba319b5SDimitry Andric static_assert(_Count >= 0, "Count must be >= 0 in span::last()"); 2734ba319b5SDimitry Andric static_assert(_Count <= _Extent, "Count out of range in span::last()"); 2744ba319b5SDimitry Andric return {data() + size() - _Count, _Count}; 2754ba319b5SDimitry Andric } 2764ba319b5SDimitry Andric 2774ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2784ba319b5SDimitry Andric constexpr span<element_type, dynamic_extent> first(index_type __count) const noexcept 2794ba319b5SDimitry Andric { 2804ba319b5SDimitry Andric _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::first(count)"); 2814ba319b5SDimitry Andric return {data(), __count}; 2824ba319b5SDimitry Andric } 2834ba319b5SDimitry Andric 2844ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2854ba319b5SDimitry Andric constexpr span<element_type, dynamic_extent> last(index_type __count) const noexcept 2864ba319b5SDimitry Andric { 2874ba319b5SDimitry Andric _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::last(count)"); 2884ba319b5SDimitry Andric return {data() + size() - __count, __count}; 2894ba319b5SDimitry Andric } 2904ba319b5SDimitry Andric 2914ba319b5SDimitry Andric template <ptrdiff_t _Offset, ptrdiff_t _Count = dynamic_extent> 2924ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 2934ba319b5SDimitry Andric constexpr auto subspan() const noexcept 2944ba319b5SDimitry Andric -> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset> 2954ba319b5SDimitry Andric { 2964ba319b5SDimitry Andric _LIBCPP_ASSERT(_Offset >= 0 && _Offset <= size(), "Offset out of range in span::subspan()"); 2974ba319b5SDimitry Andric return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; 2984ba319b5SDimitry Andric } 2994ba319b5SDimitry Andric 3004ba319b5SDimitry Andric 3014ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 3024ba319b5SDimitry Andric constexpr span<element_type, dynamic_extent> 3034ba319b5SDimitry Andric subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept 3044ba319b5SDimitry Andric { 3054ba319b5SDimitry Andric _LIBCPP_ASSERT( __offset >= 0 && __offset <= size(), "Offset out of range in span::subspan(offset, count)"); 3064ba319b5SDimitry Andric _LIBCPP_ASSERT((__count >= 0 && __count <= size()) || __count == dynamic_extent, "Count out of range in span::subspan(offset, count)"); 3074ba319b5SDimitry Andric if (__count == dynamic_extent) 3084ba319b5SDimitry Andric return {data() + __offset, size() - __offset}; 3094ba319b5SDimitry Andric _LIBCPP_ASSERT(__offset + __count <= size(), "count + offset out of range in span::subspan(offset, count)"); 3104ba319b5SDimitry Andric return {data() + __offset, __count}; 3114ba319b5SDimitry Andric } 3124ba319b5SDimitry Andric 3134ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr index_type size() const noexcept { return _Extent; } 3144ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return _Extent * sizeof(element_type); } 3154ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return _Extent == 0; } 3164ba319b5SDimitry Andric 3174ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept 3184ba319b5SDimitry Andric { 3194ba319b5SDimitry Andric _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T,N>[] index out of bounds"); 3204ba319b5SDimitry Andric return __data[__idx]; 3214ba319b5SDimitry Andric } 3224ba319b5SDimitry Andric 3234ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept 3244ba319b5SDimitry Andric { 3254ba319b5SDimitry Andric _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T,N>() index out of bounds"); 3264ba319b5SDimitry Andric return __data[__idx]; 3274ba319b5SDimitry Andric } 3284ba319b5SDimitry Andric 3294ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } 3304ba319b5SDimitry Andric 3314ba319b5SDimitry Andric// [span.iter], span iterator support 3324ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); } 3334ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); } 3344ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); } 3354ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); } 3364ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } 3374ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } 3384ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); } 3394ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); } 3404ba319b5SDimitry Andric 3414ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept 3424ba319b5SDimitry Andric { 3434ba319b5SDimitry Andric pointer __p = __data; 3444ba319b5SDimitry Andric __data = __other.__data; 3454ba319b5SDimitry Andric __other.__data = __p; 3464ba319b5SDimitry Andric } 3474ba319b5SDimitry Andric 3484ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept 3494ba319b5SDimitry Andric { return {reinterpret_cast<const byte *>(data()), size_bytes()}; } 3504ba319b5SDimitry Andric 3514ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY span<byte, _Extent * sizeof(element_type)> __as_writeable_bytes() const noexcept 3524ba319b5SDimitry Andric { return {reinterpret_cast<byte *>(data()), size_bytes()}; } 3534ba319b5SDimitry Andric 3544ba319b5SDimitry Andricprivate: 3554ba319b5SDimitry Andric pointer __data; 3564ba319b5SDimitry Andric 3574ba319b5SDimitry Andric}; 3584ba319b5SDimitry Andric 3594ba319b5SDimitry Andric 3604ba319b5SDimitry Andrictemplate <typename _Tp> 3614ba319b5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> { 3624ba319b5SDimitry Andricprivate: 3634ba319b5SDimitry Andric 3644ba319b5SDimitry Andricpublic: 3654ba319b5SDimitry Andric// constants and types 3664ba319b5SDimitry Andric using element_type = _Tp; 3674ba319b5SDimitry Andric using value_type = remove_cv_t<_Tp>; 3684ba319b5SDimitry Andric using index_type = ptrdiff_t; 3694ba319b5SDimitry Andric using difference_type = ptrdiff_t; 3704ba319b5SDimitry Andric using pointer = _Tp *; 3714ba319b5SDimitry Andric using const_pointer = const _Tp *; // not in standard 3724ba319b5SDimitry Andric using reference = _Tp &; 3734ba319b5SDimitry Andric using const_reference = const _Tp &; // not in standard 3744ba319b5SDimitry Andric using iterator = __wrap_iter<pointer>; 3754ba319b5SDimitry Andric using const_iterator = __wrap_iter<const_pointer>; 3764ba319b5SDimitry Andric using reverse_iterator = _VSTD::reverse_iterator<iterator>; 3774ba319b5SDimitry Andric using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>; 3784ba319b5SDimitry Andric 3794ba319b5SDimitry Andric static constexpr index_type extent = dynamic_extent; 3804ba319b5SDimitry Andric 3814ba319b5SDimitry Andric// [span.cons], span constructors, copy, assignment, and destructor 3824ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} {} 3834ba319b5SDimitry Andric 3844ba319b5SDimitry Andric constexpr span (const span&) noexcept = default; 3854ba319b5SDimitry Andric constexpr span& operator=(const span&) noexcept = default; 3864ba319b5SDimitry Andric 3874ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr}, __size{__count} {} 3884ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{distance(__f, __l)} {} 3894ba319b5SDimitry Andric 3904ba319b5SDimitry Andric template <size_t _Sz> 3914ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 3924ba319b5SDimitry Andric constexpr span(element_type (&__arr)[_Sz]) noexcept : __data{__arr}, __size{_Sz} {} 3934ba319b5SDimitry Andric 3944ba319b5SDimitry Andric template <size_t _Sz> 3954ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 3964ba319b5SDimitry Andric constexpr span(array<value_type, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {} 3974ba319b5SDimitry Andric 3984ba319b5SDimitry Andric template <size_t _Sz> 3994ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 4004ba319b5SDimitry Andric constexpr span(const array<value_type, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {} 4014ba319b5SDimitry Andric 4024ba319b5SDimitry Andric template <class _Container> 4034ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 4044ba319b5SDimitry Andric constexpr span( _Container& __c, 4054ba319b5SDimitry Andric enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr) 4064ba319b5SDimitry Andric : __data{_VSTD::data(__c)}, __size{(index_type) _VSTD::size(__c)} {} 4074ba319b5SDimitry Andric 4084ba319b5SDimitry Andric template <class _Container> 4094ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 4104ba319b5SDimitry Andric constexpr span(const _Container& __c, 4114ba319b5SDimitry Andric enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr) 4124ba319b5SDimitry Andric : __data{_VSTD::data(__c)}, __size{(index_type) _VSTD::size(__c)} {} 4134ba319b5SDimitry Andric 4144ba319b5SDimitry Andric 4154ba319b5SDimitry Andric template <class _OtherElementType, ptrdiff_t _OtherExtent> 4164ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 4174ba319b5SDimitry Andric constexpr span(const span<_OtherElementType, _OtherExtent>& __other, 4184ba319b5SDimitry Andric enable_if_t< 4194ba319b5SDimitry Andric is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, 4204ba319b5SDimitry Andric nullptr_t> = nullptr) noexcept 4214ba319b5SDimitry Andric : __data{__other.data()}, __size{__other.size()} {} 4224ba319b5SDimitry Andric 4234ba319b5SDimitry Andric// ~span() noexcept = default; 4244ba319b5SDimitry Andric 4254ba319b5SDimitry Andric template <ptrdiff_t _Count> 4264ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 4274ba319b5SDimitry Andric constexpr span<element_type, _Count> first() const noexcept 4284ba319b5SDimitry Andric { 429*b5893f02SDimitry Andric static_assert(_Count >= 0, "Count must be >= 0 in span::first()"); 4304ba319b5SDimitry Andric _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()"); 4314ba319b5SDimitry Andric return {data(), _Count}; 4324ba319b5SDimitry Andric } 4334ba319b5SDimitry Andric 4344ba319b5SDimitry Andric template <ptrdiff_t _Count> 4354ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 4364ba319b5SDimitry Andric constexpr span<element_type, _Count> last() const noexcept 4374ba319b5SDimitry Andric { 438*b5893f02SDimitry Andric static_assert(_Count >= 0, "Count must be >= 0 in span::last()"); 4394ba319b5SDimitry Andric _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()"); 4404ba319b5SDimitry Andric return {data() + size() - _Count, _Count}; 4414ba319b5SDimitry Andric } 4424ba319b5SDimitry Andric 4434ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4444ba319b5SDimitry Andric constexpr span<element_type, dynamic_extent> first(index_type __count) const noexcept 4454ba319b5SDimitry Andric { 4464ba319b5SDimitry Andric _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::first(count)"); 4474ba319b5SDimitry Andric return {data(), __count}; 4484ba319b5SDimitry Andric } 4494ba319b5SDimitry Andric 4504ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4514ba319b5SDimitry Andric constexpr span<element_type, dynamic_extent> last (index_type __count) const noexcept 4524ba319b5SDimitry Andric { 4534ba319b5SDimitry Andric _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::last(count)"); 4544ba319b5SDimitry Andric return {data() + size() - __count, __count}; 4554ba319b5SDimitry Andric } 4564ba319b5SDimitry Andric 4574ba319b5SDimitry Andric template <ptrdiff_t _Offset, ptrdiff_t _Count = dynamic_extent> 4584ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 4594ba319b5SDimitry Andric constexpr span<_Tp, dynamic_extent> subspan() const noexcept 4604ba319b5SDimitry Andric { 4614ba319b5SDimitry Andric _LIBCPP_ASSERT(_Offset >= 0 && _Offset <= size(), "Offset out of range in span::subspan()"); 4624ba319b5SDimitry Andric _LIBCPP_ASSERT(_Count == dynamic_extent || _Offset + _Count <= size(), "Count out of range in span::subspan()"); 4634ba319b5SDimitry Andric return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; 4644ba319b5SDimitry Andric } 4654ba319b5SDimitry Andric 4664ba319b5SDimitry Andric constexpr span<element_type, dynamic_extent> 4674ba319b5SDimitry Andric inline _LIBCPP_INLINE_VISIBILITY 4684ba319b5SDimitry Andric subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept 4694ba319b5SDimitry Andric { 4704ba319b5SDimitry Andric _LIBCPP_ASSERT( __offset >= 0 && __offset <= size(), "Offset out of range in span::subspan(offset, count)"); 4714ba319b5SDimitry Andric _LIBCPP_ASSERT((__count >= 0 && __count <= size()) || __count == dynamic_extent, "count out of range in span::subspan(offset, count)"); 4724ba319b5SDimitry Andric if (__count == dynamic_extent) 4734ba319b5SDimitry Andric return {data() + __offset, size() - __offset}; 4744ba319b5SDimitry Andric _LIBCPP_ASSERT(__offset + __count <= size(), "Offset + count out of range in span::subspan(offset, count)"); 4754ba319b5SDimitry Andric return {data() + __offset, __count}; 4764ba319b5SDimitry Andric } 4774ba319b5SDimitry Andric 4784ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr index_type size() const noexcept { return __size; } 4794ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return __size * sizeof(element_type); } 4804ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return __size == 0; } 4814ba319b5SDimitry Andric 4824ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept 4834ba319b5SDimitry Andric { 4844ba319b5SDimitry Andric _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T>[] index out of bounds"); 4854ba319b5SDimitry Andric return __data[__idx]; 4864ba319b5SDimitry Andric } 4874ba319b5SDimitry Andric 4884ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept 4894ba319b5SDimitry Andric { 4904ba319b5SDimitry Andric _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T>() index out of bounds"); 4914ba319b5SDimitry Andric return __data[__idx]; 4924ba319b5SDimitry Andric } 4934ba319b5SDimitry Andric 4944ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } 4954ba319b5SDimitry Andric 4964ba319b5SDimitry Andric// [span.iter], span iterator support 4974ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); } 4984ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); } 4994ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); } 5004ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); } 5014ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } 5024ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } 5034ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); } 5044ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); } 5054ba319b5SDimitry Andric 5064ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept 5074ba319b5SDimitry Andric { 5084ba319b5SDimitry Andric pointer __p = __data; 5094ba319b5SDimitry Andric __data = __other.__data; 5104ba319b5SDimitry Andric __other.__data = __p; 5114ba319b5SDimitry Andric 5124ba319b5SDimitry Andric index_type __sz = __size; 5134ba319b5SDimitry Andric __size = __other.__size; 5144ba319b5SDimitry Andric __other.__size = __sz; 5154ba319b5SDimitry Andric } 5164ba319b5SDimitry Andric 5174ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY span<const byte, dynamic_extent> __as_bytes() const noexcept 5184ba319b5SDimitry Andric { return {reinterpret_cast<const byte *>(data()), size_bytes()}; } 5194ba319b5SDimitry Andric 5204ba319b5SDimitry Andric _LIBCPP_INLINE_VISIBILITY span<byte, dynamic_extent> __as_writeable_bytes() const noexcept 5214ba319b5SDimitry Andric { return {reinterpret_cast<byte *>(data()), size_bytes()}; } 5224ba319b5SDimitry Andric 5234ba319b5SDimitry Andricprivate: 5244ba319b5SDimitry Andric pointer __data; 5254ba319b5SDimitry Andric index_type __size; 5264ba319b5SDimitry Andric}; 5274ba319b5SDimitry Andric 5284ba319b5SDimitry Andric// as_bytes & as_writeable_bytes 5294ba319b5SDimitry Andrictemplate <class _Tp, ptrdiff_t _Extent> 5304ba319b5SDimitry Andric auto as_bytes(span<_Tp, _Extent> __s) noexcept 5314ba319b5SDimitry Andric -> decltype(__s.__as_bytes()) 5324ba319b5SDimitry Andric { return __s.__as_bytes(); } 5334ba319b5SDimitry Andric 5344ba319b5SDimitry Andrictemplate <class _Tp, ptrdiff_t _Extent> 5354ba319b5SDimitry Andric auto as_writeable_bytes(span<_Tp, _Extent> __s) noexcept 5364ba319b5SDimitry Andric -> typename enable_if<!is_const_v<_Tp>, decltype(__s.__as_writeable_bytes())>::type 5374ba319b5SDimitry Andric { return __s.__as_writeable_bytes(); } 5384ba319b5SDimitry Andric 5394ba319b5SDimitry Andrictemplate <class _Tp, ptrdiff_t _Extent> 5404ba319b5SDimitry Andric constexpr void swap(span<_Tp, _Extent> &__lhs, span<_Tp, _Extent> &__rhs) noexcept 5414ba319b5SDimitry Andric { __lhs.swap(__rhs); } 5424ba319b5SDimitry Andric 5434ba319b5SDimitry Andric 5444ba319b5SDimitry Andric// Deduction guides 5454ba319b5SDimitry Andrictemplate<class _Tp, size_t _Sz> 5464ba319b5SDimitry Andric span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>; 5474ba319b5SDimitry Andric 5484ba319b5SDimitry Andrictemplate<class _Tp, size_t _Sz> 5494ba319b5SDimitry Andric span(array<_Tp, _Sz>&) -> span<_Tp, _Sz>; 5504ba319b5SDimitry Andric 5514ba319b5SDimitry Andrictemplate<class _Tp, size_t _Sz> 5524ba319b5SDimitry Andric span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>; 5534ba319b5SDimitry Andric 5544ba319b5SDimitry Andrictemplate<class _Container> 5554ba319b5SDimitry Andric span(_Container&) -> span<typename _Container::value_type>; 5564ba319b5SDimitry Andric 5574ba319b5SDimitry Andrictemplate<class _Container> 5584ba319b5SDimitry Andric span(const _Container&) -> span<const typename _Container::value_type>; 5594ba319b5SDimitry Andric 5604ba319b5SDimitry Andric#endif // _LIBCPP_STD_VER > 17 5614ba319b5SDimitry Andric 5624ba319b5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 5634ba319b5SDimitry Andric 5644ba319b5SDimitry Andric#endif // _LIBCPP_SPAN 565