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