xref: /freebsd/contrib/llvm-project/libcxx/include/span (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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