xref: /freebsd/contrib/llvm-project/libcxx/include/span (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
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
250b57cec5SDimitry Andric// [span.objectrep], views of object representation
260b57cec5SDimitry Andrictemplate <class ElementType, size_t Extent>
270b57cec5SDimitry Andric    span<const byte, ((Extent == dynamic_extent) ? dynamic_extent :
280b57cec5SDimitry Andric        (sizeof(ElementType) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept;
290b57cec5SDimitry Andric
300b57cec5SDimitry Andrictemplate <class ElementType, size_t Extent>
310b57cec5SDimitry Andric    span<      byte, ((Extent == dynamic_extent) ? dynamic_extent :
320b57cec5SDimitry Andric        (sizeof(ElementType) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept;
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric
350b57cec5SDimitry Andricnamespace std {
360b57cec5SDimitry Andrictemplate <class ElementType, size_t Extent = dynamic_extent>
370b57cec5SDimitry Andricclass span {
380b57cec5SDimitry Andricpublic:
390b57cec5SDimitry Andric    // constants and types
400b57cec5SDimitry Andric    using element_type = ElementType;
410b57cec5SDimitry Andric    using value_type = remove_cv_t<ElementType>;
42480093f4SDimitry Andric    using size_type = size_t;
430b57cec5SDimitry Andric    using difference_type = ptrdiff_t;
440b57cec5SDimitry Andric    using pointer = element_type*;
450b57cec5SDimitry Andric    using const_pointer = const element_type*;
460b57cec5SDimitry Andric    using reference = element_type&;
470b57cec5SDimitry Andric    using const_reference = const element_type&;
480b57cec5SDimitry Andric    using iterator = implementation-defined;
490b57cec5SDimitry Andric    using reverse_iterator = std::reverse_iterator<iterator>;
50480093f4SDimitry Andric    static constexpr size_type extent = Extent;
510b57cec5SDimitry Andric
520b57cec5SDimitry Andric    // [span.cons], span constructors, copy, assignment, and destructor
530b57cec5SDimitry Andric    constexpr span() noexcept;
545ffd83dbSDimitry Andric    constexpr explicit(Extent != dynamic_extent) span(pointer ptr, size_type count);
555ffd83dbSDimitry Andric    constexpr explicit(Extent != dynamic_extent) span(pointer firstElem, pointer lastElem);
560b57cec5SDimitry Andric    template <size_t N>
570b57cec5SDimitry Andric        constexpr span(element_type (&arr)[N]) noexcept;
580b57cec5SDimitry Andric    template <size_t N>
590b57cec5SDimitry Andric        constexpr span(array<value_type, N>& arr) noexcept;
600b57cec5SDimitry Andric    template <size_t N>
610b57cec5SDimitry Andric        constexpr span(const array<value_type, N>& arr) noexcept;
620b57cec5SDimitry Andric    template <class Container>
635ffd83dbSDimitry Andric        constexpr explicit(Extent != dynamic_extent) span(Container& cont);
640b57cec5SDimitry Andric    template <class Container>
655ffd83dbSDimitry Andric        constexpr explicit(Extent != dynamic_extent) span(const Container& cont);
660b57cec5SDimitry Andric    constexpr span(const span& other) noexcept = default;
670b57cec5SDimitry Andric    template <class OtherElementType, size_t OtherExtent>
685ffd83dbSDimitry Andric        constexpr explicit(Extent != dynamic_extent) span(const span<OtherElementType, OtherExtent>& s) noexcept;
690b57cec5SDimitry Andric    ~span() noexcept = default;
700b57cec5SDimitry Andric    constexpr span& operator=(const span& other) noexcept = default;
710b57cec5SDimitry Andric
720b57cec5SDimitry Andric    // [span.sub], span subviews
730b57cec5SDimitry Andric    template <size_t Count>
740b57cec5SDimitry Andric        constexpr span<element_type, Count> first() const;
750b57cec5SDimitry Andric    template <size_t Count>
760b57cec5SDimitry Andric        constexpr span<element_type, Count> last() const;
770b57cec5SDimitry Andric    template <size_t Offset, size_t Count = dynamic_extent>
780b57cec5SDimitry Andric        constexpr span<element_type, see below> subspan() const;
790b57cec5SDimitry Andric
80480093f4SDimitry Andric    constexpr span<element_type, dynamic_extent> first(size_type count) const;
81480093f4SDimitry Andric    constexpr span<element_type, dynamic_extent> last(size_type count) const;
82480093f4SDimitry Andric    constexpr span<element_type, dynamic_extent> subspan(size_type offset, size_type count = dynamic_extent) const;
830b57cec5SDimitry Andric
840b57cec5SDimitry Andric    // [span.obs], span observers
85480093f4SDimitry Andric    constexpr size_type size() const noexcept;
86480093f4SDimitry Andric    constexpr size_type size_bytes() const noexcept;
870b57cec5SDimitry Andric    constexpr bool empty() const noexcept;
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric    // [span.elem], span element access
90480093f4SDimitry Andric    constexpr reference operator[](size_type idx) const;
910b57cec5SDimitry Andric    constexpr reference front() const;
920b57cec5SDimitry Andric    constexpr reference back() const;
930b57cec5SDimitry Andric    constexpr pointer data() const noexcept;
940b57cec5SDimitry Andric
950b57cec5SDimitry Andric    // [span.iterators], span iterator support
960b57cec5SDimitry Andric    constexpr iterator begin() const noexcept;
970b57cec5SDimitry Andric    constexpr iterator end() const noexcept;
980b57cec5SDimitry Andric    constexpr reverse_iterator rbegin() const noexcept;
990b57cec5SDimitry Andric    constexpr reverse_iterator rend() const noexcept;
1000b57cec5SDimitry Andric
1010b57cec5SDimitry Andricprivate:
1020b57cec5SDimitry Andric    pointer data_;    // exposition only
103480093f4SDimitry Andric    size_type size_;  // exposition only
1040b57cec5SDimitry Andric};
1050b57cec5SDimitry Andric
1060b57cec5SDimitry Andrictemplate<class T, size_t N>
1070b57cec5SDimitry Andric    span(T (&)[N]) -> span<T, N>;
1080b57cec5SDimitry Andric
1090b57cec5SDimitry Andrictemplate<class T, size_t N>
1100b57cec5SDimitry Andric    span(array<T, N>&) -> span<T, N>;
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andrictemplate<class T, size_t N>
1130b57cec5SDimitry Andric    span(const array<T, N>&) -> span<const T, N>;
1140b57cec5SDimitry Andric
1150b57cec5SDimitry Andrictemplate<class Container>
1160b57cec5SDimitry Andric    span(Container&) -> span<typename Container::value_type>;
1170b57cec5SDimitry Andric
1180b57cec5SDimitry Andrictemplate<class Container>
1190b57cec5SDimitry Andric    span(const Container&) -> span<const typename Container::value_type>;
1200b57cec5SDimitry Andric
1210b57cec5SDimitry Andric} // namespace std
1220b57cec5SDimitry Andric
1230b57cec5SDimitry Andric*/
1240b57cec5SDimitry Andric
1250b57cec5SDimitry Andric#include <__config>
1260b57cec5SDimitry Andric#include <array>        // for array
1270b57cec5SDimitry Andric#include <cstddef>      // for byte
1285ffd83dbSDimitry Andric#include <iterator>     // for iterators
1295ffd83dbSDimitry Andric#include <type_traits>  // for remove_cv, etc
1300b57cec5SDimitry Andric
1310b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1320b57cec5SDimitry Andric#pragma GCC system_header
1330b57cec5SDimitry Andric#endif
1340b57cec5SDimitry Andric
135*e8d8bef9SDimitry Andric_LIBCPP_PUSH_MACROS
136*e8d8bef9SDimitry Andric#include <__undef_macros>
137*e8d8bef9SDimitry Andric
1380b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric#if _LIBCPP_STD_VER > 17
1410b57cec5SDimitry Andric
142*e8d8bef9SDimitry Andricinline constexpr size_t dynamic_extent = numeric_limits<size_t>::max();
1430b57cec5SDimitry Andrictemplate <typename _Tp, size_t _Extent = dynamic_extent> class span;
1440b57cec5SDimitry Andric
1450b57cec5SDimitry Andric
1460b57cec5SDimitry Andrictemplate <class _Tp>
1470b57cec5SDimitry Andricstruct __is_span_impl : public false_type {};
1480b57cec5SDimitry Andric
1490b57cec5SDimitry Andrictemplate <class _Tp, size_t _Extent>
1500b57cec5SDimitry Andricstruct __is_span_impl<span<_Tp, _Extent>> : public true_type {};
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andrictemplate <class _Tp>
1530b57cec5SDimitry Andricstruct __is_span : public __is_span_impl<remove_cv_t<_Tp>> {};
1540b57cec5SDimitry Andric
1550b57cec5SDimitry Andrictemplate <class _Tp>
1560b57cec5SDimitry Andricstruct __is_std_array_impl : public false_type {};
1570b57cec5SDimitry Andric
1580b57cec5SDimitry Andrictemplate <class _Tp, size_t _Sz>
1590b57cec5SDimitry Andricstruct __is_std_array_impl<array<_Tp, _Sz>> : public true_type {};
1600b57cec5SDimitry Andric
1610b57cec5SDimitry Andrictemplate <class _Tp>
1620b57cec5SDimitry Andricstruct __is_std_array : public __is_std_array_impl<remove_cv_t<_Tp>> {};
1630b57cec5SDimitry Andric
1640b57cec5SDimitry Andrictemplate <class _Tp, class _ElementType, class = void>
1650b57cec5SDimitry Andricstruct __is_span_compatible_container : public false_type {};
1660b57cec5SDimitry Andric
1670b57cec5SDimitry Andrictemplate <class _Tp, class _ElementType>
1680b57cec5SDimitry Andricstruct __is_span_compatible_container<_Tp, _ElementType,
1690b57cec5SDimitry Andric        void_t<
1700b57cec5SDimitry Andric        // is not a specialization of span
1710b57cec5SDimitry Andric            typename enable_if<!__is_span<_Tp>::value, nullptr_t>::type,
1720b57cec5SDimitry Andric        // is not a specialization of array
1730b57cec5SDimitry Andric            typename enable_if<!__is_std_array<_Tp>::value, nullptr_t>::type,
1740b57cec5SDimitry Andric        // is_array_v<Container> is false,
1750b57cec5SDimitry Andric            typename enable_if<!is_array_v<_Tp>, nullptr_t>::type,
1760b57cec5SDimitry Andric        // data(cont) and size(cont) are well formed
1770b57cec5SDimitry Andric            decltype(data(declval<_Tp>())),
1780b57cec5SDimitry Andric            decltype(size(declval<_Tp>())),
1790b57cec5SDimitry Andric        // remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[]
1800b57cec5SDimitry Andric            typename enable_if<
1810b57cec5SDimitry Andric                is_convertible_v<remove_pointer_t<decltype(data(declval<_Tp &>()))>(*)[],
1820b57cec5SDimitry Andric                                 _ElementType(*)[]>,
1830b57cec5SDimitry Andric                nullptr_t>::type
1840b57cec5SDimitry Andric        >>
1850b57cec5SDimitry Andric    : public true_type {};
1860b57cec5SDimitry Andric
1870b57cec5SDimitry Andric
1880b57cec5SDimitry Andrictemplate <typename _Tp, size_t _Extent>
1890b57cec5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS span {
1900b57cec5SDimitry Andricpublic:
1910b57cec5SDimitry Andric//  constants and types
1920b57cec5SDimitry Andric    using element_type           = _Tp;
1930b57cec5SDimitry Andric    using value_type             = remove_cv_t<_Tp>;
194480093f4SDimitry Andric    using size_type              = size_t;
1950b57cec5SDimitry Andric    using difference_type        = ptrdiff_t;
1960b57cec5SDimitry Andric    using pointer                = _Tp *;
1970b57cec5SDimitry Andric    using const_pointer          = const _Tp *;
1980b57cec5SDimitry Andric    using reference              = _Tp &;
1990b57cec5SDimitry Andric    using const_reference        = const _Tp &;
2000b57cec5SDimitry Andric    using iterator               =  __wrap_iter<pointer>;
2010b57cec5SDimitry Andric    using reverse_iterator       = _VSTD::reverse_iterator<iterator>;
2020b57cec5SDimitry Andric
203480093f4SDimitry Andric    static constexpr size_type extent = _Extent;
2040b57cec5SDimitry Andric
2050b57cec5SDimitry Andric// [span.cons], span constructors, copy, assignment, and destructor
2065ffd83dbSDimitry Andric    template <size_t _Sz = _Extent, enable_if_t<_Sz == 0, nullptr_t> = nullptr>
2075ffd83dbSDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr} {}
2080b57cec5SDimitry Andric
2090b57cec5SDimitry Andric    constexpr span           (const span&) noexcept = default;
2100b57cec5SDimitry Andric    constexpr span& operator=(const span&) noexcept = default;
2110b57cec5SDimitry Andric
2125ffd83dbSDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr explicit span(pointer __ptr, size_type __count) : __data{__ptr}
2130b57cec5SDimitry Andric        { (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); }
2145ffd83dbSDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr explicit span(pointer __f, pointer __l) : __data{__f}
2150b57cec5SDimitry Andric        { (void)__l;     _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); }
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent])          noexcept : __data{__arr} {}
2185ffd83dbSDimitry Andric
2195ffd83dbSDimitry Andric    template <class _OtherElementType,
2205ffd83dbSDimitry Andric              enable_if_t<is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
2215ffd83dbSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2225ffd83dbSDimitry Andric    constexpr span(array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {}
2235ffd83dbSDimitry Andric
2245ffd83dbSDimitry Andric    template <class _OtherElementType,
2255ffd83dbSDimitry Andric              enable_if_t<is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
2265ffd83dbSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2275ffd83dbSDimitry Andric    constexpr span(const array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {}
2285ffd83dbSDimitry Andric
2295ffd83dbSDimitry Andric    template <class _Container>
2305ffd83dbSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2315ffd83dbSDimitry Andric        constexpr explicit span(      _Container& __c,
2325ffd83dbSDimitry Andric            enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
2335ffd83dbSDimitry Andric        : __data{_VSTD::data(__c)} {
2345ffd83dbSDimitry Andric            _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (range)");
2355ffd83dbSDimitry Andric        }
2365ffd83dbSDimitry Andric
2375ffd83dbSDimitry Andric    template <class _Container>
2385ffd83dbSDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2395ffd83dbSDimitry Andric        constexpr explicit span(const _Container& __c,
2405ffd83dbSDimitry Andric            enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
2415ffd83dbSDimitry Andric        : __data{_VSTD::data(__c)} {
2425ffd83dbSDimitry Andric            _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (range)");
2435ffd83dbSDimitry Andric        }
2440b57cec5SDimitry Andric
2450b57cec5SDimitry Andric    template <class _OtherElementType>
2460b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2470b57cec5SDimitry Andric        constexpr span(const span<_OtherElementType, _Extent>& __other,
2480b57cec5SDimitry Andric                       enable_if_t<
2490b57cec5SDimitry Andric                          is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
2500b57cec5SDimitry Andric                          nullptr_t> = nullptr)
2510b57cec5SDimitry Andric        : __data{__other.data()} {}
2520b57cec5SDimitry Andric
2530b57cec5SDimitry Andric    template <class _OtherElementType>
2540b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2555ffd83dbSDimitry Andric        constexpr explicit span(const span<_OtherElementType, dynamic_extent>& __other,
2560b57cec5SDimitry Andric                       enable_if_t<
2570b57cec5SDimitry Andric                          is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
2580b57cec5SDimitry Andric                          nullptr_t> = nullptr) noexcept
2590b57cec5SDimitry Andric        : __data{__other.data()} { _LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); }
2600b57cec5SDimitry Andric
2610b57cec5SDimitry Andric
2620b57cec5SDimitry Andric//  ~span() noexcept = default;
2630b57cec5SDimitry Andric
2640b57cec5SDimitry Andric    template <size_t _Count>
2650b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2660b57cec5SDimitry Andric    constexpr span<element_type, _Count> first() const noexcept
2670b57cec5SDimitry Andric    {
2680b57cec5SDimitry Andric        static_assert(_Count <= _Extent, "Count out of range in span::first()");
2695ffd83dbSDimitry Andric        return span<element_type, _Count>{data(), _Count};
2700b57cec5SDimitry Andric    }
2710b57cec5SDimitry Andric
2720b57cec5SDimitry Andric    template <size_t _Count>
2730b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2740b57cec5SDimitry Andric    constexpr span<element_type, _Count> last() const noexcept
2750b57cec5SDimitry Andric    {
2760b57cec5SDimitry Andric        static_assert(_Count <= _Extent, "Count out of range in span::last()");
2775ffd83dbSDimitry Andric        return span<element_type, _Count>{data() + size() - _Count, _Count};
2780b57cec5SDimitry Andric    }
2790b57cec5SDimitry Andric
2800b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
281480093f4SDimitry Andric    constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept
2820b57cec5SDimitry Andric    {
2830b57cec5SDimitry Andric        _LIBCPP_ASSERT(__count <= size(), "Count out of range in span::first(count)");
2840b57cec5SDimitry Andric        return {data(), __count};
2850b57cec5SDimitry Andric    }
2860b57cec5SDimitry Andric
2870b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
288480093f4SDimitry Andric    constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept
2890b57cec5SDimitry Andric    {
2900b57cec5SDimitry Andric        _LIBCPP_ASSERT(__count <= size(), "Count out of range in span::last(count)");
2910b57cec5SDimitry Andric        return {data() + size() - __count, __count};
2920b57cec5SDimitry Andric    }
2930b57cec5SDimitry Andric
2940b57cec5SDimitry Andric    template <size_t _Offset, size_t _Count = dynamic_extent>
2950b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
2960b57cec5SDimitry Andric    constexpr auto subspan() const noexcept
2970b57cec5SDimitry Andric        -> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>
2980b57cec5SDimitry Andric    {
2990b57cec5SDimitry Andric        static_assert(_Offset <= _Extent, "Offset out of range in span::subspan()");
3005ffd83dbSDimitry Andric        static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset, "Offset + count out of range in span::subspan()");
3015ffd83dbSDimitry Andric
3025ffd83dbSDimitry Andric        using _ReturnType = span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>;
3035ffd83dbSDimitry Andric        return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
3040b57cec5SDimitry Andric    }
3050b57cec5SDimitry Andric
3060b57cec5SDimitry Andric
3070b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3080b57cec5SDimitry Andric    constexpr span<element_type, dynamic_extent>
309480093f4SDimitry Andric       subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept
3100b57cec5SDimitry Andric    {
3110b57cec5SDimitry Andric        _LIBCPP_ASSERT(__offset <= size(), "Offset out of range in span::subspan(offset, count)");
3120b57cec5SDimitry Andric        _LIBCPP_ASSERT(__count  <= size() || __count == dynamic_extent, "Count out of range in span::subspan(offset, count)");
3130b57cec5SDimitry Andric        if (__count == dynamic_extent)
3140b57cec5SDimitry Andric            return {data() + __offset, size() - __offset};
3155ffd83dbSDimitry Andric        _LIBCPP_ASSERT(__count <= size() - __offset, "Offset + count out of range in span::subspan(offset, count)");
3160b57cec5SDimitry Andric        return {data() + __offset, __count};
3170b57cec5SDimitry Andric    }
3180b57cec5SDimitry Andric
319480093f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr size_type size()       const noexcept { return _Extent; }
320480093f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr size_type size_bytes() const noexcept { return _Extent * sizeof(element_type); }
3210b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr bool empty()           const noexcept { return _Extent == 0; }
3220b57cec5SDimitry Andric
323480093f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept
3240b57cec5SDimitry Andric    {
3255ffd83dbSDimitry Andric        _LIBCPP_ASSERT(__idx < size(), "span<T,N>[] index out of bounds");
3260b57cec5SDimitry Andric        return __data[__idx];
3270b57cec5SDimitry Andric    }
3280b57cec5SDimitry Andric
3290b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept
3300b57cec5SDimitry Andric    {
3315ffd83dbSDimitry Andric        _LIBCPP_ASSERT(!empty(), "span<T, N>::front() on empty span");
3320b57cec5SDimitry Andric        return __data[0];
3330b57cec5SDimitry Andric    }
3340b57cec5SDimitry Andric
3350b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept
3360b57cec5SDimitry Andric    {
3375ffd83dbSDimitry Andric        _LIBCPP_ASSERT(!empty(), "span<T, N>::back() on empty span");
3380b57cec5SDimitry Andric        return __data[size()-1];
3390b57cec5SDimitry Andric    }
3400b57cec5SDimitry Andric
3410b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr pointer data()                         const noexcept { return __data; }
3420b57cec5SDimitry Andric
3430b57cec5SDimitry Andric// [span.iter], span iterator support
3440b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr iterator                 begin() const noexcept { return iterator(data()); }
3450b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr iterator                   end() const noexcept { return iterator(data() + size()); }
3460b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator        rbegin() const noexcept { return reverse_iterator(end()); }
3470b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator          rend() const noexcept { return reverse_iterator(begin()); }
3480b57cec5SDimitry Andric
3490b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept
3505ffd83dbSDimitry Andric    { return span<const byte, _Extent * sizeof(element_type)>{reinterpret_cast<const byte *>(data()), size_bytes()}; }
3510b57cec5SDimitry Andric
3520b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY span<byte, _Extent * sizeof(element_type)> __as_writable_bytes() const noexcept
3535ffd83dbSDimitry Andric    { return span<byte, _Extent * sizeof(element_type)>{reinterpret_cast<byte *>(data()), size_bytes()}; }
3540b57cec5SDimitry Andric
3550b57cec5SDimitry Andricprivate:
3560b57cec5SDimitry Andric    pointer    __data;
3570b57cec5SDimitry Andric
3580b57cec5SDimitry Andric};
3590b57cec5SDimitry Andric
3600b57cec5SDimitry Andric
3610b57cec5SDimitry Andrictemplate <typename _Tp>
3620b57cec5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> {
3630b57cec5SDimitry Andricprivate:
3640b57cec5SDimitry Andric
3650b57cec5SDimitry Andricpublic:
3660b57cec5SDimitry Andric//  constants and types
3670b57cec5SDimitry Andric    using element_type           = _Tp;
3680b57cec5SDimitry Andric    using value_type             = remove_cv_t<_Tp>;
369480093f4SDimitry Andric    using size_type              = size_t;
3700b57cec5SDimitry Andric    using difference_type        = ptrdiff_t;
3710b57cec5SDimitry Andric    using pointer                = _Tp *;
3720b57cec5SDimitry Andric    using const_pointer          = const _Tp *;
3730b57cec5SDimitry Andric    using reference              = _Tp &;
3740b57cec5SDimitry Andric    using const_reference        = const _Tp &;
3750b57cec5SDimitry Andric    using iterator               =  __wrap_iter<pointer>;
3760b57cec5SDimitry Andric    using reverse_iterator       = _VSTD::reverse_iterator<iterator>;
3770b57cec5SDimitry Andric
378480093f4SDimitry Andric    static constexpr size_type extent = dynamic_extent;
3790b57cec5SDimitry Andric
3800b57cec5SDimitry Andric// [span.cons], span constructors, copy, assignment, and destructor
3810b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} {}
3820b57cec5SDimitry Andric
3830b57cec5SDimitry Andric    constexpr span           (const span&) noexcept = default;
3840b57cec5SDimitry Andric    constexpr span& operator=(const span&) noexcept = default;
3850b57cec5SDimitry Andric
386480093f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, size_type __count) : __data{__ptr}, __size{__count} {}
3870b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{static_cast<size_t>(distance(__f, __l))} {}
3880b57cec5SDimitry Andric
3890b57cec5SDimitry Andric    template <size_t _Sz>
3900b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3910b57cec5SDimitry Andric    constexpr span(element_type (&__arr)[_Sz])          noexcept : __data{__arr}, __size{_Sz} {}
3920b57cec5SDimitry Andric
3935ffd83dbSDimitry Andric    template <class _OtherElementType, size_t _Sz,
3945ffd83dbSDimitry Andric              enable_if_t<is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
3950b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
3965ffd83dbSDimitry Andric    constexpr span(array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
3970b57cec5SDimitry Andric
3985ffd83dbSDimitry Andric    template <class _OtherElementType, size_t _Sz,
3995ffd83dbSDimitry Andric              enable_if_t<is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
4000b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4015ffd83dbSDimitry Andric    constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
4020b57cec5SDimitry Andric
4030b57cec5SDimitry Andric    template <class _Container>
4040b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4050b57cec5SDimitry Andric        constexpr span(      _Container& __c,
4060b57cec5SDimitry Andric            enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
407480093f4SDimitry Andric        : __data{_VSTD::data(__c)}, __size{(size_type) _VSTD::size(__c)} {}
4080b57cec5SDimitry Andric
4090b57cec5SDimitry Andric    template <class _Container>
4100b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4110b57cec5SDimitry Andric        constexpr span(const _Container& __c,
4120b57cec5SDimitry Andric            enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
413480093f4SDimitry Andric        : __data{_VSTD::data(__c)}, __size{(size_type) _VSTD::size(__c)} {}
4140b57cec5SDimitry Andric
4150b57cec5SDimitry Andric
4160b57cec5SDimitry Andric    template <class _OtherElementType, size_t _OtherExtent>
4170b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4180b57cec5SDimitry Andric        constexpr span(const span<_OtherElementType, _OtherExtent>& __other,
4190b57cec5SDimitry Andric                       enable_if_t<
4200b57cec5SDimitry Andric                          is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
4210b57cec5SDimitry Andric                          nullptr_t> = nullptr) noexcept
4220b57cec5SDimitry Andric        : __data{__other.data()}, __size{__other.size()} {}
4230b57cec5SDimitry Andric
4240b57cec5SDimitry Andric//    ~span() noexcept = default;
4250b57cec5SDimitry Andric
4260b57cec5SDimitry Andric    template <size_t _Count>
4270b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4280b57cec5SDimitry Andric    constexpr span<element_type, _Count> first() const noexcept
4290b57cec5SDimitry Andric    {
4300b57cec5SDimitry Andric        _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()");
4315ffd83dbSDimitry Andric        return span<element_type, _Count>{data(), _Count};
4320b57cec5SDimitry Andric    }
4330b57cec5SDimitry Andric
4340b57cec5SDimitry Andric    template <size_t _Count>
4350b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4360b57cec5SDimitry Andric    constexpr span<element_type, _Count> last() const noexcept
4370b57cec5SDimitry Andric    {
4380b57cec5SDimitry Andric        _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()");
4395ffd83dbSDimitry Andric        return span<element_type, _Count>{data() + size() - _Count, _Count};
4400b57cec5SDimitry Andric    }
4410b57cec5SDimitry Andric
4420b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
443480093f4SDimitry Andric    constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept
4440b57cec5SDimitry Andric    {
4450b57cec5SDimitry Andric        _LIBCPP_ASSERT(__count <= size(), "Count out of range in span::first(count)");
4460b57cec5SDimitry Andric        return {data(), __count};
4470b57cec5SDimitry Andric    }
4480b57cec5SDimitry Andric
4490b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
450480093f4SDimitry Andric    constexpr span<element_type, dynamic_extent> last (size_type __count) const noexcept
4510b57cec5SDimitry Andric    {
4520b57cec5SDimitry Andric        _LIBCPP_ASSERT(__count <= size(), "Count out of range in span::last(count)");
4530b57cec5SDimitry Andric        return {data() + size() - __count, __count};
4540b57cec5SDimitry Andric    }
4550b57cec5SDimitry Andric
4560b57cec5SDimitry Andric    template <size_t _Offset, size_t _Count = dynamic_extent>
4570b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
4585ffd83dbSDimitry Andric    constexpr span<element_type, _Count> subspan() const noexcept
4590b57cec5SDimitry Andric    {
4600b57cec5SDimitry Andric        _LIBCPP_ASSERT(_Offset <= size(), "Offset out of range in span::subspan()");
4615ffd83dbSDimitry Andric        _LIBCPP_ASSERT(_Count == dynamic_extent || _Count <= size() - _Offset, "Offset + count out of range in span::subspan()");
4625ffd83dbSDimitry Andric        return span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
4630b57cec5SDimitry Andric    }
4640b57cec5SDimitry Andric
4650b57cec5SDimitry Andric    constexpr span<element_type, dynamic_extent>
4660b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
467480093f4SDimitry Andric    subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept
4680b57cec5SDimitry Andric    {
4690b57cec5SDimitry Andric        _LIBCPP_ASSERT(__offset <= size(), "Offset out of range in span::subspan(offset, count)");
4700b57cec5SDimitry Andric        _LIBCPP_ASSERT(__count  <= size() || __count == dynamic_extent, "count out of range in span::subspan(offset, count)");
4710b57cec5SDimitry Andric        if (__count == dynamic_extent)
4720b57cec5SDimitry Andric            return {data() + __offset, size() - __offset};
4735ffd83dbSDimitry Andric        _LIBCPP_ASSERT(__count <= size() - __offset, "Offset + count out of range in span::subspan(offset, count)");
4740b57cec5SDimitry Andric        return {data() + __offset, __count};
4750b57cec5SDimitry Andric    }
4760b57cec5SDimitry Andric
477480093f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr size_type size()       const noexcept { return __size; }
478480093f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr size_type size_bytes() const noexcept { return __size * sizeof(element_type); }
4790b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr bool empty()           const noexcept { return __size == 0; }
4800b57cec5SDimitry Andric
481480093f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept
4820b57cec5SDimitry Andric    {
4835ffd83dbSDimitry Andric        _LIBCPP_ASSERT(__idx < size(), "span<T>[] index out of bounds");
4840b57cec5SDimitry Andric        return __data[__idx];
4850b57cec5SDimitry Andric    }
4860b57cec5SDimitry Andric
4870b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept
4880b57cec5SDimitry Andric    {
4890b57cec5SDimitry Andric        _LIBCPP_ASSERT(!empty(), "span<T>[].front() on empty span");
4900b57cec5SDimitry Andric        return __data[0];
4910b57cec5SDimitry Andric    }
4920b57cec5SDimitry Andric
4930b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept
4940b57cec5SDimitry Andric    {
4950b57cec5SDimitry Andric        _LIBCPP_ASSERT(!empty(), "span<T>[].back() on empty span");
4960b57cec5SDimitry Andric        return __data[size()-1];
4970b57cec5SDimitry Andric    }
4980b57cec5SDimitry Andric
4990b57cec5SDimitry Andric
5000b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr pointer data()                         const noexcept { return __data; }
5010b57cec5SDimitry Andric
5020b57cec5SDimitry Andric// [span.iter], span iterator support
5030b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr iterator                 begin() const noexcept { return iterator(data()); }
5040b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr iterator                   end() const noexcept { return iterator(data() + size()); }
5050b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator        rbegin() const noexcept { return reverse_iterator(end()); }
5060b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator          rend() const noexcept { return reverse_iterator(begin()); }
5070b57cec5SDimitry Andric
5080b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY span<const byte, dynamic_extent> __as_bytes() const noexcept
5090b57cec5SDimitry Andric    { return {reinterpret_cast<const byte *>(data()), size_bytes()}; }
5100b57cec5SDimitry Andric
5110b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY span<byte, dynamic_extent> __as_writable_bytes() const noexcept
5120b57cec5SDimitry Andric    { return {reinterpret_cast<byte *>(data()), size_bytes()}; }
5130b57cec5SDimitry Andric
5140b57cec5SDimitry Andricprivate:
5150b57cec5SDimitry Andric    pointer   __data;
516480093f4SDimitry Andric    size_type __size;
5170b57cec5SDimitry Andric};
5180b57cec5SDimitry Andric
5190b57cec5SDimitry Andric//  as_bytes & as_writable_bytes
5200b57cec5SDimitry Andrictemplate <class _Tp, size_t _Extent>
5210b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
5220b57cec5SDimitry Andricauto as_bytes(span<_Tp, _Extent> __s) noexcept
5230b57cec5SDimitry Andric-> decltype(__s.__as_bytes())
5240b57cec5SDimitry Andric{ return    __s.__as_bytes(); }
5250b57cec5SDimitry Andric
5260b57cec5SDimitry Andrictemplate <class _Tp, size_t _Extent>
5270b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
5280b57cec5SDimitry Andricauto as_writable_bytes(span<_Tp, _Extent> __s) noexcept
5290b57cec5SDimitry Andric-> enable_if_t<!is_const_v<_Tp>, decltype(__s.__as_writable_bytes())>
5300b57cec5SDimitry Andric{ return __s.__as_writable_bytes(); }
5310b57cec5SDimitry Andric
5320b57cec5SDimitry Andric//  Deduction guides
5330b57cec5SDimitry Andrictemplate<class _Tp, size_t _Sz>
5340b57cec5SDimitry Andric    span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>;
5350b57cec5SDimitry Andric
5360b57cec5SDimitry Andrictemplate<class _Tp, size_t _Sz>
5370b57cec5SDimitry Andric    span(array<_Tp, _Sz>&) -> span<_Tp, _Sz>;
5380b57cec5SDimitry Andric
5390b57cec5SDimitry Andrictemplate<class _Tp, size_t _Sz>
5400b57cec5SDimitry Andric    span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>;
5410b57cec5SDimitry Andric
5420b57cec5SDimitry Andrictemplate<class _Container>
5430b57cec5SDimitry Andric    span(_Container&) -> span<typename _Container::value_type>;
5440b57cec5SDimitry Andric
5450b57cec5SDimitry Andrictemplate<class _Container>
5460b57cec5SDimitry Andric    span(const _Container&) -> span<const typename _Container::value_type>;
5470b57cec5SDimitry Andric
5480b57cec5SDimitry Andric#endif // _LIBCPP_STD_VER > 17
5490b57cec5SDimitry Andric
5500b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
5510b57cec5SDimitry Andric
552*e8d8bef9SDimitry Andric_LIBCPP_POP_MACROS
553*e8d8bef9SDimitry Andric
5540b57cec5SDimitry Andric#endif // _LIBCPP_SPAN
555