10b57cec5SDimitry Andric// -*- C++ -*- 20b57cec5SDimitry Andric//===------------------------------ span ---------------------------------===// 30b57cec5SDimitry Andric// 40b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 50b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information. 60b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70b57cec5SDimitry Andric// 80b57cec5SDimitry Andric//===---------------------------------------------------------------------===// 90b57cec5SDimitry Andric 100b57cec5SDimitry Andric#ifndef _LIBCPP_SPAN 110b57cec5SDimitry Andric#define _LIBCPP_SPAN 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric/* 140b57cec5SDimitry Andric span synopsis 150b57cec5SDimitry Andric 160b57cec5SDimitry Andricnamespace std { 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric// constants 190b57cec5SDimitry Andricinline constexpr size_t dynamic_extent = numeric_limits<size_t>::max(); 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric// [views.span], class template span 220b57cec5SDimitry Andrictemplate <class ElementType, size_t Extent = dynamic_extent> 230b57cec5SDimitry Andric class span; 240b57cec5SDimitry Andric 25*fe6060f1SDimitry Andrictemplate<class ElementType, size_t Extent> 26*fe6060f1SDimitry Andric inline constexpr bool ranges::enable_view<span<ElementType, Extent>> = true; 27*fe6060f1SDimitry Andric 28*fe6060f1SDimitry Andrictemplate<class ElementType, size_t Extent> 29*fe6060f1SDimitry Andric inline constexpr bool ranges::enable_borrowed_range<span<ElementType, Extent>> = true; 30*fe6060f1SDimitry Andric 310b57cec5SDimitry Andric// [span.objectrep], views of object representation 320b57cec5SDimitry Andrictemplate <class ElementType, size_t Extent> 330b57cec5SDimitry Andric span<const byte, ((Extent == dynamic_extent) ? dynamic_extent : 340b57cec5SDimitry Andric (sizeof(ElementType) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andrictemplate <class ElementType, size_t Extent> 370b57cec5SDimitry Andric span< byte, ((Extent == dynamic_extent) ? dynamic_extent : 380b57cec5SDimitry Andric (sizeof(ElementType) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept; 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric 410b57cec5SDimitry Andrictemplate <class ElementType, size_t Extent = dynamic_extent> 420b57cec5SDimitry Andricclass span { 430b57cec5SDimitry Andricpublic: 440b57cec5SDimitry Andric // constants and types 450b57cec5SDimitry Andric using element_type = ElementType; 460b57cec5SDimitry Andric using value_type = remove_cv_t<ElementType>; 47480093f4SDimitry Andric using size_type = size_t; 480b57cec5SDimitry Andric using difference_type = ptrdiff_t; 490b57cec5SDimitry Andric using pointer = element_type*; 500b57cec5SDimitry Andric using const_pointer = const element_type*; 510b57cec5SDimitry Andric using reference = element_type&; 520b57cec5SDimitry Andric using const_reference = const element_type&; 530b57cec5SDimitry Andric using iterator = implementation-defined; 540b57cec5SDimitry Andric using reverse_iterator = std::reverse_iterator<iterator>; 55480093f4SDimitry Andric static constexpr size_type extent = Extent; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric // [span.cons], span constructors, copy, assignment, and destructor 580b57cec5SDimitry Andric constexpr span() noexcept; 595ffd83dbSDimitry Andric constexpr explicit(Extent != dynamic_extent) span(pointer ptr, size_type count); 605ffd83dbSDimitry Andric constexpr explicit(Extent != dynamic_extent) span(pointer firstElem, pointer lastElem); 610b57cec5SDimitry Andric template <size_t N> 620b57cec5SDimitry Andric constexpr span(element_type (&arr)[N]) noexcept; 630b57cec5SDimitry Andric template <size_t N> 640b57cec5SDimitry Andric constexpr span(array<value_type, N>& arr) noexcept; 650b57cec5SDimitry Andric template <size_t N> 660b57cec5SDimitry Andric constexpr span(const array<value_type, N>& arr) noexcept; 670b57cec5SDimitry Andric template <class Container> 685ffd83dbSDimitry Andric constexpr explicit(Extent != dynamic_extent) span(Container& cont); 690b57cec5SDimitry Andric template <class Container> 705ffd83dbSDimitry Andric constexpr explicit(Extent != dynamic_extent) span(const Container& cont); 710b57cec5SDimitry Andric constexpr span(const span& other) noexcept = default; 720b57cec5SDimitry Andric template <class OtherElementType, size_t OtherExtent> 735ffd83dbSDimitry Andric constexpr explicit(Extent != dynamic_extent) span(const span<OtherElementType, OtherExtent>& s) noexcept; 740b57cec5SDimitry Andric ~span() noexcept = default; 750b57cec5SDimitry Andric constexpr span& operator=(const span& other) noexcept = default; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric // [span.sub], span subviews 780b57cec5SDimitry Andric template <size_t Count> 790b57cec5SDimitry Andric constexpr span<element_type, Count> first() const; 800b57cec5SDimitry Andric template <size_t Count> 810b57cec5SDimitry Andric constexpr span<element_type, Count> last() const; 820b57cec5SDimitry Andric template <size_t Offset, size_t Count = dynamic_extent> 830b57cec5SDimitry Andric constexpr span<element_type, see below> subspan() const; 840b57cec5SDimitry Andric 85480093f4SDimitry Andric constexpr span<element_type, dynamic_extent> first(size_type count) const; 86480093f4SDimitry Andric constexpr span<element_type, dynamic_extent> last(size_type count) const; 87480093f4SDimitry Andric constexpr span<element_type, dynamic_extent> subspan(size_type offset, size_type count = dynamic_extent) const; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric // [span.obs], span observers 90480093f4SDimitry Andric constexpr size_type size() const noexcept; 91480093f4SDimitry Andric constexpr size_type size_bytes() const noexcept; 920b57cec5SDimitry Andric constexpr bool empty() const noexcept; 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric // [span.elem], span element access 95480093f4SDimitry Andric constexpr reference operator[](size_type idx) const; 960b57cec5SDimitry Andric constexpr reference front() const; 970b57cec5SDimitry Andric constexpr reference back() const; 980b57cec5SDimitry Andric constexpr pointer data() const noexcept; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric // [span.iterators], span iterator support 1010b57cec5SDimitry Andric constexpr iterator begin() const noexcept; 1020b57cec5SDimitry Andric constexpr iterator end() const noexcept; 1030b57cec5SDimitry Andric constexpr reverse_iterator rbegin() const noexcept; 1040b57cec5SDimitry Andric constexpr reverse_iterator rend() const noexcept; 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andricprivate: 1070b57cec5SDimitry Andric pointer data_; // exposition only 108480093f4SDimitry Andric size_type size_; // exposition only 1090b57cec5SDimitry Andric}; 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andrictemplate<class T, size_t N> 1120b57cec5SDimitry Andric span(T (&)[N]) -> span<T, N>; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andrictemplate<class T, size_t N> 1150b57cec5SDimitry Andric span(array<T, N>&) -> span<T, N>; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andrictemplate<class T, size_t N> 1180b57cec5SDimitry Andric span(const array<T, N>&) -> span<const T, N>; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andrictemplate<class Container> 1210b57cec5SDimitry Andric span(Container&) -> span<typename Container::value_type>; 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andrictemplate<class Container> 1240b57cec5SDimitry Andric span(const Container&) -> span<const typename Container::value_type>; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric} // namespace std 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric*/ 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric#include <__config> 131*fe6060f1SDimitry Andric#include <__debug> 132*fe6060f1SDimitry Andric#include <__iterator/wrap_iter.h> 133*fe6060f1SDimitry Andric#include <__ranges/enable_borrowed_range.h> 134*fe6060f1SDimitry Andric#include <__ranges/enable_view.h> 1350b57cec5SDimitry Andric#include <array> // for array 1360b57cec5SDimitry Andric#include <cstddef> // for byte 1375ffd83dbSDimitry Andric#include <iterator> // for iterators 138*fe6060f1SDimitry Andric#include <limits> 1395ffd83dbSDimitry Andric#include <type_traits> // for remove_cv, etc 140*fe6060f1SDimitry Andric#include <version> 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 1430b57cec5SDimitry Andric#pragma GCC system_header 1440b57cec5SDimitry Andric#endif 1450b57cec5SDimitry Andric 146e8d8bef9SDimitry Andric_LIBCPP_PUSH_MACROS 147e8d8bef9SDimitry Andric#include <__undef_macros> 148e8d8bef9SDimitry Andric 1490b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric#if _LIBCPP_STD_VER > 17 1520b57cec5SDimitry Andric 153e8d8bef9SDimitry Andricinline constexpr size_t dynamic_extent = numeric_limits<size_t>::max(); 1540b57cec5SDimitry Andrictemplate <typename _Tp, size_t _Extent = dynamic_extent> class span; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andrictemplate <class _Tp> 1580b57cec5SDimitry Andricstruct __is_span_impl : public false_type {}; 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andrictemplate <class _Tp, size_t _Extent> 1610b57cec5SDimitry Andricstruct __is_span_impl<span<_Tp, _Extent>> : public true_type {}; 1620b57cec5SDimitry Andric 1630b57cec5SDimitry Andrictemplate <class _Tp> 1640b57cec5SDimitry Andricstruct __is_span : public __is_span_impl<remove_cv_t<_Tp>> {}; 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andrictemplate <class _Tp> 1670b57cec5SDimitry Andricstruct __is_std_array_impl : public false_type {}; 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andrictemplate <class _Tp, size_t _Sz> 1700b57cec5SDimitry Andricstruct __is_std_array_impl<array<_Tp, _Sz>> : public true_type {}; 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andrictemplate <class _Tp> 1730b57cec5SDimitry Andricstruct __is_std_array : public __is_std_array_impl<remove_cv_t<_Tp>> {}; 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andrictemplate <class _Tp, class _ElementType, class = void> 1760b57cec5SDimitry Andricstruct __is_span_compatible_container : public false_type {}; 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andrictemplate <class _Tp, class _ElementType> 1790b57cec5SDimitry Andricstruct __is_span_compatible_container<_Tp, _ElementType, 1800b57cec5SDimitry Andric void_t< 1810b57cec5SDimitry Andric // is not a specialization of span 1820b57cec5SDimitry Andric typename enable_if<!__is_span<_Tp>::value, nullptr_t>::type, 1830b57cec5SDimitry Andric // is not a specialization of array 1840b57cec5SDimitry Andric typename enable_if<!__is_std_array<_Tp>::value, nullptr_t>::type, 1850b57cec5SDimitry Andric // is_array_v<Container> is false, 1860b57cec5SDimitry Andric typename enable_if<!is_array_v<_Tp>, nullptr_t>::type, 1870b57cec5SDimitry Andric // data(cont) and size(cont) are well formed 1880b57cec5SDimitry Andric decltype(data(declval<_Tp>())), 1890b57cec5SDimitry Andric decltype(size(declval<_Tp>())), 1900b57cec5SDimitry Andric // remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[] 1910b57cec5SDimitry Andric typename enable_if< 1920b57cec5SDimitry Andric is_convertible_v<remove_pointer_t<decltype(data(declval<_Tp &>()))>(*)[], 1930b57cec5SDimitry Andric _ElementType(*)[]>, 1940b57cec5SDimitry Andric nullptr_t>::type 1950b57cec5SDimitry Andric >> 1960b57cec5SDimitry Andric : public true_type {}; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andrictemplate <typename _Tp, size_t _Extent> 2000b57cec5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS span { 2010b57cec5SDimitry Andricpublic: 2020b57cec5SDimitry Andric// constants and types 2030b57cec5SDimitry Andric using element_type = _Tp; 2040b57cec5SDimitry Andric using value_type = remove_cv_t<_Tp>; 205480093f4SDimitry Andric using size_type = size_t; 2060b57cec5SDimitry Andric using difference_type = ptrdiff_t; 2070b57cec5SDimitry Andric using pointer = _Tp *; 2080b57cec5SDimitry Andric using const_pointer = const _Tp *; 2090b57cec5SDimitry Andric using reference = _Tp &; 2100b57cec5SDimitry Andric using const_reference = const _Tp &; 211*fe6060f1SDimitry Andric#if (_LIBCPP_DEBUG_LEVEL == 2) || defined(_LIBCPP_ABI_SPAN_POINTER_ITERATORS) 212*fe6060f1SDimitry Andric using iterator = pointer; 213*fe6060f1SDimitry Andric#else 2140b57cec5SDimitry Andric using iterator = __wrap_iter<pointer>; 215*fe6060f1SDimitry Andric#endif 2160b57cec5SDimitry Andric using reverse_iterator = _VSTD::reverse_iterator<iterator>; 2170b57cec5SDimitry Andric 218480093f4SDimitry Andric static constexpr size_type extent = _Extent; 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric// [span.cons], span constructors, copy, assignment, and destructor 2215ffd83dbSDimitry Andric template <size_t _Sz = _Extent, enable_if_t<_Sz == 0, nullptr_t> = nullptr> 2225ffd83dbSDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr} {} 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric constexpr span (const span&) noexcept = default; 2250b57cec5SDimitry Andric constexpr span& operator=(const span&) noexcept = default; 2260b57cec5SDimitry Andric 2275ffd83dbSDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr explicit span(pointer __ptr, size_type __count) : __data{__ptr} 2280b57cec5SDimitry Andric { (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); } 2295ffd83dbSDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr explicit span(pointer __f, pointer __l) : __data{__f} 2300b57cec5SDimitry Andric { (void)__l; _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent]) noexcept : __data{__arr} {} 2335ffd83dbSDimitry Andric 2345ffd83dbSDimitry Andric template <class _OtherElementType, 2355ffd83dbSDimitry Andric enable_if_t<is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr> 2365ffd83dbSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2375ffd83dbSDimitry Andric constexpr span(array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {} 2385ffd83dbSDimitry Andric 2395ffd83dbSDimitry Andric template <class _OtherElementType, 2405ffd83dbSDimitry Andric enable_if_t<is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr> 2415ffd83dbSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2425ffd83dbSDimitry Andric constexpr span(const array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {} 2435ffd83dbSDimitry Andric 2445ffd83dbSDimitry Andric template <class _Container> 2455ffd83dbSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2465ffd83dbSDimitry Andric constexpr explicit span( _Container& __c, 2475ffd83dbSDimitry Andric enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr) 2485ffd83dbSDimitry Andric : __data{_VSTD::data(__c)} { 2495ffd83dbSDimitry Andric _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (range)"); 2505ffd83dbSDimitry Andric } 2515ffd83dbSDimitry Andric 2525ffd83dbSDimitry Andric template <class _Container> 2535ffd83dbSDimitry Andric _LIBCPP_INLINE_VISIBILITY 2545ffd83dbSDimitry Andric constexpr explicit span(const _Container& __c, 2555ffd83dbSDimitry Andric enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr) 2565ffd83dbSDimitry Andric : __data{_VSTD::data(__c)} { 2575ffd83dbSDimitry Andric _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (range)"); 2585ffd83dbSDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric template <class _OtherElementType> 2610b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2620b57cec5SDimitry Andric constexpr span(const span<_OtherElementType, _Extent>& __other, 2630b57cec5SDimitry Andric enable_if_t< 2640b57cec5SDimitry Andric is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, 2650b57cec5SDimitry Andric nullptr_t> = nullptr) 2660b57cec5SDimitry Andric : __data{__other.data()} {} 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric template <class _OtherElementType> 2690b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2705ffd83dbSDimitry Andric constexpr explicit span(const span<_OtherElementType, dynamic_extent>& __other, 2710b57cec5SDimitry Andric enable_if_t< 2720b57cec5SDimitry Andric is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, 2730b57cec5SDimitry Andric nullptr_t> = nullptr) noexcept 2740b57cec5SDimitry Andric : __data{__other.data()} { _LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); } 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric// ~span() noexcept = default; 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric template <size_t _Count> 2800b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2810b57cec5SDimitry Andric constexpr span<element_type, _Count> first() const noexcept 2820b57cec5SDimitry Andric { 2830b57cec5SDimitry Andric static_assert(_Count <= _Extent, "Count out of range in span::first()"); 2845ffd83dbSDimitry Andric return span<element_type, _Count>{data(), _Count}; 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric template <size_t _Count> 2880b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 2890b57cec5SDimitry Andric constexpr span<element_type, _Count> last() const noexcept 2900b57cec5SDimitry Andric { 2910b57cec5SDimitry Andric static_assert(_Count <= _Extent, "Count out of range in span::last()"); 2925ffd83dbSDimitry Andric return span<element_type, _Count>{data() + size() - _Count, _Count}; 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 296480093f4SDimitry Andric constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept 2970b57cec5SDimitry Andric { 2980b57cec5SDimitry Andric _LIBCPP_ASSERT(__count <= size(), "Count out of range in span::first(count)"); 2990b57cec5SDimitry Andric return {data(), __count}; 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 303480093f4SDimitry Andric constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept 3040b57cec5SDimitry Andric { 3050b57cec5SDimitry Andric _LIBCPP_ASSERT(__count <= size(), "Count out of range in span::last(count)"); 3060b57cec5SDimitry Andric return {data() + size() - __count, __count}; 3070b57cec5SDimitry Andric } 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric template <size_t _Offset, size_t _Count = dynamic_extent> 3100b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3110b57cec5SDimitry Andric constexpr auto subspan() const noexcept 3120b57cec5SDimitry Andric -> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset> 3130b57cec5SDimitry Andric { 3140b57cec5SDimitry Andric static_assert(_Offset <= _Extent, "Offset out of range in span::subspan()"); 3155ffd83dbSDimitry Andric static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset, "Offset + count out of range in span::subspan()"); 3165ffd83dbSDimitry Andric 3175ffd83dbSDimitry Andric using _ReturnType = span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>; 3185ffd83dbSDimitry Andric return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; 3190b57cec5SDimitry Andric } 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 3230b57cec5SDimitry Andric constexpr span<element_type, dynamic_extent> 324480093f4SDimitry Andric subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept 3250b57cec5SDimitry Andric { 3260b57cec5SDimitry Andric _LIBCPP_ASSERT(__offset <= size(), "Offset out of range in span::subspan(offset, count)"); 3270b57cec5SDimitry Andric _LIBCPP_ASSERT(__count <= size() || __count == dynamic_extent, "Count out of range in span::subspan(offset, count)"); 3280b57cec5SDimitry Andric if (__count == dynamic_extent) 3290b57cec5SDimitry Andric return {data() + __offset, size() - __offset}; 3305ffd83dbSDimitry Andric _LIBCPP_ASSERT(__count <= size() - __offset, "Offset + count out of range in span::subspan(offset, count)"); 3310b57cec5SDimitry Andric return {data() + __offset, __count}; 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 334480093f4SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr size_type size() const noexcept { return _Extent; } 335480093f4SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr size_type size_bytes() const noexcept { return _Extent * sizeof(element_type); } 3360b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return _Extent == 0; } 3370b57cec5SDimitry Andric 338480093f4SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept 3390b57cec5SDimitry Andric { 3405ffd83dbSDimitry Andric _LIBCPP_ASSERT(__idx < size(), "span<T,N>[] index out of bounds"); 3410b57cec5SDimitry Andric return __data[__idx]; 3420b57cec5SDimitry Andric } 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept 3450b57cec5SDimitry Andric { 3465ffd83dbSDimitry Andric _LIBCPP_ASSERT(!empty(), "span<T, N>::front() on empty span"); 3470b57cec5SDimitry Andric return __data[0]; 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept 3510b57cec5SDimitry Andric { 3525ffd83dbSDimitry Andric _LIBCPP_ASSERT(!empty(), "span<T, N>::back() on empty span"); 3530b57cec5SDimitry Andric return __data[size()-1]; 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric// [span.iter], span iterator support 3590b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); } 3600b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); } 3610b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } 3620b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept 3655ffd83dbSDimitry Andric { return span<const byte, _Extent * sizeof(element_type)>{reinterpret_cast<const byte *>(data()), size_bytes()}; } 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY span<byte, _Extent * sizeof(element_type)> __as_writable_bytes() const noexcept 3685ffd83dbSDimitry Andric { return span<byte, _Extent * sizeof(element_type)>{reinterpret_cast<byte *>(data()), size_bytes()}; } 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andricprivate: 3710b57cec5SDimitry Andric pointer __data; 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric}; 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andrictemplate <typename _Tp> 3770b57cec5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> { 3780b57cec5SDimitry Andricprivate: 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andricpublic: 3810b57cec5SDimitry Andric// constants and types 3820b57cec5SDimitry Andric using element_type = _Tp; 3830b57cec5SDimitry Andric using value_type = remove_cv_t<_Tp>; 384480093f4SDimitry Andric using size_type = size_t; 3850b57cec5SDimitry Andric using difference_type = ptrdiff_t; 3860b57cec5SDimitry Andric using pointer = _Tp *; 3870b57cec5SDimitry Andric using const_pointer = const _Tp *; 3880b57cec5SDimitry Andric using reference = _Tp &; 3890b57cec5SDimitry Andric using const_reference = const _Tp &; 390*fe6060f1SDimitry Andric#if (_LIBCPP_DEBUG_LEVEL == 2) || defined(_LIBCPP_ABI_SPAN_POINTER_ITERATORS) 391*fe6060f1SDimitry Andric using iterator = pointer; 392*fe6060f1SDimitry Andric#else 3930b57cec5SDimitry Andric using iterator = __wrap_iter<pointer>; 394*fe6060f1SDimitry Andric#endif 3950b57cec5SDimitry Andric using reverse_iterator = _VSTD::reverse_iterator<iterator>; 3960b57cec5SDimitry Andric 397480093f4SDimitry Andric static constexpr size_type extent = dynamic_extent; 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric// [span.cons], span constructors, copy, assignment, and destructor 4000b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} {} 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric constexpr span (const span&) noexcept = default; 4030b57cec5SDimitry Andric constexpr span& operator=(const span&) noexcept = default; 4040b57cec5SDimitry Andric 405480093f4SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, size_type __count) : __data{__ptr}, __size{__count} {} 4060b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{static_cast<size_t>(distance(__f, __l))} {} 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric template <size_t _Sz> 4090b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4100b57cec5SDimitry Andric constexpr span(element_type (&__arr)[_Sz]) noexcept : __data{__arr}, __size{_Sz} {} 4110b57cec5SDimitry Andric 4125ffd83dbSDimitry Andric template <class _OtherElementType, size_t _Sz, 4135ffd83dbSDimitry Andric enable_if_t<is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr> 4140b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4155ffd83dbSDimitry Andric constexpr span(array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {} 4160b57cec5SDimitry Andric 4175ffd83dbSDimitry Andric template <class _OtherElementType, size_t _Sz, 4185ffd83dbSDimitry Andric enable_if_t<is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr> 4190b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4205ffd83dbSDimitry Andric constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {} 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric template <class _Container> 4230b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4240b57cec5SDimitry Andric constexpr span( _Container& __c, 4250b57cec5SDimitry Andric enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr) 426480093f4SDimitry Andric : __data{_VSTD::data(__c)}, __size{(size_type) _VSTD::size(__c)} {} 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric template <class _Container> 4290b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4300b57cec5SDimitry Andric constexpr span(const _Container& __c, 4310b57cec5SDimitry Andric enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr) 432480093f4SDimitry Andric : __data{_VSTD::data(__c)}, __size{(size_type) _VSTD::size(__c)} {} 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric template <class _OtherElementType, size_t _OtherExtent> 4360b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4370b57cec5SDimitry Andric constexpr span(const span<_OtherElementType, _OtherExtent>& __other, 4380b57cec5SDimitry Andric enable_if_t< 4390b57cec5SDimitry Andric is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, 4400b57cec5SDimitry Andric nullptr_t> = nullptr) noexcept 4410b57cec5SDimitry Andric : __data{__other.data()}, __size{__other.size()} {} 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric// ~span() noexcept = default; 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric template <size_t _Count> 4460b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4470b57cec5SDimitry Andric constexpr span<element_type, _Count> first() const noexcept 4480b57cec5SDimitry Andric { 4490b57cec5SDimitry Andric _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()"); 4505ffd83dbSDimitry Andric return span<element_type, _Count>{data(), _Count}; 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric template <size_t _Count> 4540b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4550b57cec5SDimitry Andric constexpr span<element_type, _Count> last() const noexcept 4560b57cec5SDimitry Andric { 4570b57cec5SDimitry Andric _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()"); 4585ffd83dbSDimitry Andric return span<element_type, _Count>{data() + size() - _Count, _Count}; 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 462480093f4SDimitry Andric constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept 4630b57cec5SDimitry Andric { 4640b57cec5SDimitry Andric _LIBCPP_ASSERT(__count <= size(), "Count out of range in span::first(count)"); 4650b57cec5SDimitry Andric return {data(), __count}; 4660b57cec5SDimitry Andric } 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 469480093f4SDimitry Andric constexpr span<element_type, dynamic_extent> last (size_type __count) const noexcept 4700b57cec5SDimitry Andric { 4710b57cec5SDimitry Andric _LIBCPP_ASSERT(__count <= size(), "Count out of range in span::last(count)"); 4720b57cec5SDimitry Andric return {data() + size() - __count, __count}; 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric template <size_t _Offset, size_t _Count = dynamic_extent> 4760b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 4775ffd83dbSDimitry Andric constexpr span<element_type, _Count> subspan() const noexcept 4780b57cec5SDimitry Andric { 4790b57cec5SDimitry Andric _LIBCPP_ASSERT(_Offset <= size(), "Offset out of range in span::subspan()"); 4805ffd83dbSDimitry Andric _LIBCPP_ASSERT(_Count == dynamic_extent || _Count <= size() - _Offset, "Offset + count out of range in span::subspan()"); 4815ffd83dbSDimitry Andric return span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric constexpr span<element_type, dynamic_extent> 4850b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY 486480093f4SDimitry Andric subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept 4870b57cec5SDimitry Andric { 4880b57cec5SDimitry Andric _LIBCPP_ASSERT(__offset <= size(), "Offset out of range in span::subspan(offset, count)"); 4890b57cec5SDimitry Andric _LIBCPP_ASSERT(__count <= size() || __count == dynamic_extent, "count out of range in span::subspan(offset, count)"); 4900b57cec5SDimitry Andric if (__count == dynamic_extent) 4910b57cec5SDimitry Andric return {data() + __offset, size() - __offset}; 4925ffd83dbSDimitry Andric _LIBCPP_ASSERT(__count <= size() - __offset, "Offset + count out of range in span::subspan(offset, count)"); 4930b57cec5SDimitry Andric return {data() + __offset, __count}; 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric 496480093f4SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr size_type size() const noexcept { return __size; } 497480093f4SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr size_type size_bytes() const noexcept { return __size * sizeof(element_type); } 4980b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return __size == 0; } 4990b57cec5SDimitry Andric 500480093f4SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept 5010b57cec5SDimitry Andric { 5025ffd83dbSDimitry Andric _LIBCPP_ASSERT(__idx < size(), "span<T>[] index out of bounds"); 5030b57cec5SDimitry Andric return __data[__idx]; 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept 5070b57cec5SDimitry Andric { 5080b57cec5SDimitry Andric _LIBCPP_ASSERT(!empty(), "span<T>[].front() on empty span"); 5090b57cec5SDimitry Andric return __data[0]; 5100b57cec5SDimitry Andric } 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept 5130b57cec5SDimitry Andric { 5140b57cec5SDimitry Andric _LIBCPP_ASSERT(!empty(), "span<T>[].back() on empty span"); 5150b57cec5SDimitry Andric return __data[size()-1]; 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric// [span.iter], span iterator support 5220b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); } 5230b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); } 5240b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } 5250b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY span<const byte, dynamic_extent> __as_bytes() const noexcept 5280b57cec5SDimitry Andric { return {reinterpret_cast<const byte *>(data()), size_bytes()}; } 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric _LIBCPP_INLINE_VISIBILITY span<byte, dynamic_extent> __as_writable_bytes() const noexcept 5310b57cec5SDimitry Andric { return {reinterpret_cast<byte *>(data()), size_bytes()}; } 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andricprivate: 5340b57cec5SDimitry Andric pointer __data; 535480093f4SDimitry Andric size_type __size; 5360b57cec5SDimitry Andric}; 5370b57cec5SDimitry Andric 538*fe6060f1SDimitry Andric#if !defined(_LIBCPP_HAS_NO_RANGES) 539*fe6060f1SDimitry Andrictemplate <class _Tp, size_t _Extent> 540*fe6060f1SDimitry Andricinline constexpr bool ranges::enable_borrowed_range<span<_Tp, _Extent> > = true; 541*fe6060f1SDimitry Andric 542*fe6060f1SDimitry Andrictemplate <class _ElementType, size_t _Extent> 543*fe6060f1SDimitry Andricinline constexpr bool ranges::enable_view<span<_ElementType, _Extent>> = true; 544*fe6060f1SDimitry Andric#endif // !defined(_LIBCPP_HAS_NO_RANGES) 545*fe6060f1SDimitry Andric 5460b57cec5SDimitry Andric// as_bytes & as_writable_bytes 5470b57cec5SDimitry Andrictemplate <class _Tp, size_t _Extent> 5480b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY 5490b57cec5SDimitry Andricauto as_bytes(span<_Tp, _Extent> __s) noexcept 5500b57cec5SDimitry Andric-> decltype(__s.__as_bytes()) 5510b57cec5SDimitry Andric{ return __s.__as_bytes(); } 5520b57cec5SDimitry Andric 5530b57cec5SDimitry Andrictemplate <class _Tp, size_t _Extent> 5540b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY 5550b57cec5SDimitry Andricauto as_writable_bytes(span<_Tp, _Extent> __s) noexcept 5560b57cec5SDimitry Andric-> enable_if_t<!is_const_v<_Tp>, decltype(__s.__as_writable_bytes())> 5570b57cec5SDimitry Andric{ return __s.__as_writable_bytes(); } 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric// Deduction guides 5600b57cec5SDimitry Andrictemplate<class _Tp, size_t _Sz> 5610b57cec5SDimitry Andric span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>; 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andrictemplate<class _Tp, size_t _Sz> 5640b57cec5SDimitry Andric span(array<_Tp, _Sz>&) -> span<_Tp, _Sz>; 5650b57cec5SDimitry Andric 5660b57cec5SDimitry Andrictemplate<class _Tp, size_t _Sz> 5670b57cec5SDimitry Andric span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>; 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andrictemplate<class _Container> 5700b57cec5SDimitry Andric span(_Container&) -> span<typename _Container::value_type>; 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andrictemplate<class _Container> 5730b57cec5SDimitry Andric span(const _Container&) -> span<const typename _Container::value_type>; 5740b57cec5SDimitry Andric 5750b57cec5SDimitry Andric#endif // _LIBCPP_STD_VER > 17 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD 5780b57cec5SDimitry Andric 579e8d8bef9SDimitry Andric_LIBCPP_POP_MACROS 580e8d8bef9SDimitry Andric 5810b57cec5SDimitry Andric#endif // _LIBCPP_SPAN 582