xref: /freebsd/contrib/llvm-project/libcxx/include/span (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric// -*- C++ -*-
2*0b57cec5SDimitry Andric//===------------------------------ span ---------------------------------===//
3*0b57cec5SDimitry Andric//
4*0b57cec5SDimitry Andric// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*0b57cec5SDimitry Andric// See https://llvm.org/LICENSE.txt for license information.
6*0b57cec5SDimitry Andric// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*0b57cec5SDimitry Andric//
8*0b57cec5SDimitry Andric//===---------------------------------------------------------------------===//
9*0b57cec5SDimitry Andric
10*0b57cec5SDimitry Andric#ifndef _LIBCPP_SPAN
11*0b57cec5SDimitry Andric#define _LIBCPP_SPAN
12*0b57cec5SDimitry Andric
13*0b57cec5SDimitry Andric/*
14*0b57cec5SDimitry Andric    span synopsis
15*0b57cec5SDimitry Andric
16*0b57cec5SDimitry Andricnamespace std {
17*0b57cec5SDimitry Andric
18*0b57cec5SDimitry Andric// constants
19*0b57cec5SDimitry Andricinline constexpr size_t dynamic_extent = numeric_limits<size_t>::max();
20*0b57cec5SDimitry Andric
21*0b57cec5SDimitry Andric// [views.span], class template span
22*0b57cec5SDimitry Andrictemplate <class ElementType, size_t Extent = dynamic_extent>
23*0b57cec5SDimitry Andric    class span;
24*0b57cec5SDimitry Andric
25*0b57cec5SDimitry Andric// [span.objectrep], views of object representation
26*0b57cec5SDimitry Andrictemplate <class ElementType, size_t Extent>
27*0b57cec5SDimitry Andric    span<const byte, ((Extent == dynamic_extent) ? dynamic_extent :
28*0b57cec5SDimitry Andric        (sizeof(ElementType) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept;
29*0b57cec5SDimitry Andric
30*0b57cec5SDimitry Andrictemplate <class ElementType, size_t Extent>
31*0b57cec5SDimitry Andric    span<      byte, ((Extent == dynamic_extent) ? dynamic_extent :
32*0b57cec5SDimitry Andric        (sizeof(ElementType) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept;
33*0b57cec5SDimitry Andric
34*0b57cec5SDimitry Andric
35*0b57cec5SDimitry Andricnamespace std {
36*0b57cec5SDimitry Andrictemplate <class ElementType, size_t Extent = dynamic_extent>
37*0b57cec5SDimitry Andricclass span {
38*0b57cec5SDimitry Andricpublic:
39*0b57cec5SDimitry Andric    // constants and types
40*0b57cec5SDimitry Andric    using element_type = ElementType;
41*0b57cec5SDimitry Andric    using value_type = remove_cv_t<ElementType>;
42*0b57cec5SDimitry Andric    using index_type = size_t;
43*0b57cec5SDimitry Andric    using difference_type = ptrdiff_t;
44*0b57cec5SDimitry Andric    using pointer = element_type*;
45*0b57cec5SDimitry Andric    using const_pointer = const element_type*;
46*0b57cec5SDimitry Andric    using reference = element_type&;
47*0b57cec5SDimitry Andric    using const_reference = const element_type&;
48*0b57cec5SDimitry Andric    using iterator = implementation-defined;
49*0b57cec5SDimitry Andric    using const_iterator = implementation-defined;
50*0b57cec5SDimitry Andric    using reverse_iterator = std::reverse_iterator<iterator>;
51*0b57cec5SDimitry Andric    using const_reverse_iterator = std::reverse_iterator<const_iterator>;
52*0b57cec5SDimitry Andric    static constexpr index_type extent = Extent;
53*0b57cec5SDimitry Andric
54*0b57cec5SDimitry Andric    // [span.cons], span constructors, copy, assignment, and destructor
55*0b57cec5SDimitry Andric    constexpr span() noexcept;
56*0b57cec5SDimitry Andric    constexpr span(pointer ptr, index_type count);
57*0b57cec5SDimitry Andric    constexpr span(pointer firstElem, pointer lastElem);
58*0b57cec5SDimitry Andric    template <size_t N>
59*0b57cec5SDimitry Andric        constexpr span(element_type (&arr)[N]) noexcept;
60*0b57cec5SDimitry Andric    template <size_t N>
61*0b57cec5SDimitry Andric        constexpr span(array<value_type, N>& arr) noexcept;
62*0b57cec5SDimitry Andric    template <size_t N>
63*0b57cec5SDimitry Andric        constexpr span(const array<value_type, N>& arr) noexcept;
64*0b57cec5SDimitry Andric    template <class Container>
65*0b57cec5SDimitry Andric        constexpr span(Container& cont);
66*0b57cec5SDimitry Andric    template <class Container>
67*0b57cec5SDimitry Andric        constexpr span(const Container& cont);
68*0b57cec5SDimitry Andric    constexpr span(const span& other) noexcept = default;
69*0b57cec5SDimitry Andric    template <class OtherElementType, size_t OtherExtent>
70*0b57cec5SDimitry Andric        constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept;
71*0b57cec5SDimitry Andric    ~span() noexcept = default;
72*0b57cec5SDimitry Andric    constexpr span& operator=(const span& other) noexcept = default;
73*0b57cec5SDimitry Andric
74*0b57cec5SDimitry Andric    // [span.sub], span subviews
75*0b57cec5SDimitry Andric    template <size_t Count>
76*0b57cec5SDimitry Andric        constexpr span<element_type, Count> first() const;
77*0b57cec5SDimitry Andric    template <size_t Count>
78*0b57cec5SDimitry Andric        constexpr span<element_type, Count> last() const;
79*0b57cec5SDimitry Andric    template <size_t Offset, size_t Count = dynamic_extent>
80*0b57cec5SDimitry Andric        constexpr span<element_type, see below> subspan() const;
81*0b57cec5SDimitry Andric
82*0b57cec5SDimitry Andric    constexpr span<element_type, dynamic_extent> first(index_type count) const;
83*0b57cec5SDimitry Andric    constexpr span<element_type, dynamic_extent> last(index_type count) const;
84*0b57cec5SDimitry Andric    constexpr span<element_type, dynamic_extent> subspan(index_type offset, index_type count = dynamic_extent) const;
85*0b57cec5SDimitry Andric
86*0b57cec5SDimitry Andric    // [span.obs], span observers
87*0b57cec5SDimitry Andric    constexpr index_type size() const noexcept;
88*0b57cec5SDimitry Andric    constexpr index_type size_bytes() const noexcept;
89*0b57cec5SDimitry Andric    constexpr bool empty() const noexcept;
90*0b57cec5SDimitry Andric
91*0b57cec5SDimitry Andric    // [span.elem], span element access
92*0b57cec5SDimitry Andric    constexpr reference operator[](index_type idx) const;
93*0b57cec5SDimitry Andric    constexpr reference front() const;
94*0b57cec5SDimitry Andric    constexpr reference back() const;
95*0b57cec5SDimitry Andric    constexpr pointer data() const noexcept;
96*0b57cec5SDimitry Andric
97*0b57cec5SDimitry Andric    // [span.iterators], span iterator support
98*0b57cec5SDimitry Andric    constexpr iterator begin() const noexcept;
99*0b57cec5SDimitry Andric    constexpr iterator end() const noexcept;
100*0b57cec5SDimitry Andric    constexpr const_iterator cbegin() const noexcept;
101*0b57cec5SDimitry Andric    constexpr const_iterator cend() const noexcept;
102*0b57cec5SDimitry Andric    constexpr reverse_iterator rbegin() const noexcept;
103*0b57cec5SDimitry Andric    constexpr reverse_iterator rend() const noexcept;
104*0b57cec5SDimitry Andric    constexpr const_reverse_iterator crbegin() const noexcept;
105*0b57cec5SDimitry Andric    constexpr const_reverse_iterator crend() const noexcept;
106*0b57cec5SDimitry Andric
107*0b57cec5SDimitry Andricprivate:
108*0b57cec5SDimitry Andric    pointer data_;     // exposition only
109*0b57cec5SDimitry Andric    index_type size_;  // exposition only
110*0b57cec5SDimitry Andric};
111*0b57cec5SDimitry Andric
112*0b57cec5SDimitry Andrictemplate<class T, size_t N>
113*0b57cec5SDimitry Andric    span(T (&)[N]) -> span<T, N>;
114*0b57cec5SDimitry Andric
115*0b57cec5SDimitry Andrictemplate<class T, size_t N>
116*0b57cec5SDimitry Andric    span(array<T, N>&) -> span<T, N>;
117*0b57cec5SDimitry Andric
118*0b57cec5SDimitry Andrictemplate<class T, size_t N>
119*0b57cec5SDimitry Andric    span(const array<T, N>&) -> span<const T, N>;
120*0b57cec5SDimitry Andric
121*0b57cec5SDimitry Andrictemplate<class Container>
122*0b57cec5SDimitry Andric    span(Container&) -> span<typename Container::value_type>;
123*0b57cec5SDimitry Andric
124*0b57cec5SDimitry Andrictemplate<class Container>
125*0b57cec5SDimitry Andric    span(const Container&) -> span<const typename Container::value_type>;
126*0b57cec5SDimitry Andric
127*0b57cec5SDimitry Andric} // namespace std
128*0b57cec5SDimitry Andric
129*0b57cec5SDimitry Andric*/
130*0b57cec5SDimitry Andric
131*0b57cec5SDimitry Andric#include <__config>
132*0b57cec5SDimitry Andric#include <cstddef>      // for ptrdiff_t
133*0b57cec5SDimitry Andric#include <iterator>     // for iterators
134*0b57cec5SDimitry Andric#include <array>        // for array
135*0b57cec5SDimitry Andric#include <type_traits>  // for remove_cv, etc
136*0b57cec5SDimitry Andric#include <cstddef>      // for byte
137*0b57cec5SDimitry Andric
138*0b57cec5SDimitry Andric#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
139*0b57cec5SDimitry Andric#pragma GCC system_header
140*0b57cec5SDimitry Andric#endif
141*0b57cec5SDimitry Andric
142*0b57cec5SDimitry Andric_LIBCPP_BEGIN_NAMESPACE_STD
143*0b57cec5SDimitry Andric
144*0b57cec5SDimitry Andric#if _LIBCPP_STD_VER > 17
145*0b57cec5SDimitry Andric
146*0b57cec5SDimitry Andricinline constexpr size_t dynamic_extent = numeric_limits<size_t>::max();
147*0b57cec5SDimitry Andrictemplate <typename _Tp, size_t _Extent = dynamic_extent> class span;
148*0b57cec5SDimitry Andric
149*0b57cec5SDimitry Andric
150*0b57cec5SDimitry Andrictemplate <class _Tp>
151*0b57cec5SDimitry Andricstruct __is_span_impl : public false_type {};
152*0b57cec5SDimitry Andric
153*0b57cec5SDimitry Andrictemplate <class _Tp, size_t _Extent>
154*0b57cec5SDimitry Andricstruct __is_span_impl<span<_Tp, _Extent>> : public true_type {};
155*0b57cec5SDimitry Andric
156*0b57cec5SDimitry Andrictemplate <class _Tp>
157*0b57cec5SDimitry Andricstruct __is_span : public __is_span_impl<remove_cv_t<_Tp>> {};
158*0b57cec5SDimitry Andric
159*0b57cec5SDimitry Andrictemplate <class _Tp>
160*0b57cec5SDimitry Andricstruct __is_std_array_impl : public false_type {};
161*0b57cec5SDimitry Andric
162*0b57cec5SDimitry Andrictemplate <class _Tp, size_t _Sz>
163*0b57cec5SDimitry Andricstruct __is_std_array_impl<array<_Tp, _Sz>> : public true_type {};
164*0b57cec5SDimitry Andric
165*0b57cec5SDimitry Andrictemplate <class _Tp>
166*0b57cec5SDimitry Andricstruct __is_std_array : public __is_std_array_impl<remove_cv_t<_Tp>> {};
167*0b57cec5SDimitry Andric
168*0b57cec5SDimitry Andrictemplate <class _Tp, class _ElementType, class = void>
169*0b57cec5SDimitry Andricstruct __is_span_compatible_container : public false_type {};
170*0b57cec5SDimitry Andric
171*0b57cec5SDimitry Andrictemplate <class _Tp, class _ElementType>
172*0b57cec5SDimitry Andricstruct __is_span_compatible_container<_Tp, _ElementType,
173*0b57cec5SDimitry Andric        void_t<
174*0b57cec5SDimitry Andric        // is not a specialization of span
175*0b57cec5SDimitry Andric            typename enable_if<!__is_span<_Tp>::value, nullptr_t>::type,
176*0b57cec5SDimitry Andric        // is not a specialization of array
177*0b57cec5SDimitry Andric            typename enable_if<!__is_std_array<_Tp>::value, nullptr_t>::type,
178*0b57cec5SDimitry Andric        // is_array_v<Container> is false,
179*0b57cec5SDimitry Andric            typename enable_if<!is_array_v<_Tp>, nullptr_t>::type,
180*0b57cec5SDimitry Andric        // data(cont) and size(cont) are well formed
181*0b57cec5SDimitry Andric            decltype(data(declval<_Tp>())),
182*0b57cec5SDimitry Andric            decltype(size(declval<_Tp>())),
183*0b57cec5SDimitry Andric        // remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[]
184*0b57cec5SDimitry Andric            typename enable_if<
185*0b57cec5SDimitry Andric                is_convertible_v<remove_pointer_t<decltype(data(declval<_Tp &>()))>(*)[],
186*0b57cec5SDimitry Andric                                 _ElementType(*)[]>,
187*0b57cec5SDimitry Andric                nullptr_t>::type
188*0b57cec5SDimitry Andric        >>
189*0b57cec5SDimitry Andric    : public true_type {};
190*0b57cec5SDimitry Andric
191*0b57cec5SDimitry Andric
192*0b57cec5SDimitry Andrictemplate <typename _Tp, size_t _Extent>
193*0b57cec5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS span {
194*0b57cec5SDimitry Andricpublic:
195*0b57cec5SDimitry Andric//  constants and types
196*0b57cec5SDimitry Andric    using element_type           = _Tp;
197*0b57cec5SDimitry Andric    using value_type             = remove_cv_t<_Tp>;
198*0b57cec5SDimitry Andric    using index_type             = size_t;
199*0b57cec5SDimitry Andric    using difference_type        = ptrdiff_t;
200*0b57cec5SDimitry Andric    using pointer                = _Tp *;
201*0b57cec5SDimitry Andric    using const_pointer          = const _Tp *;
202*0b57cec5SDimitry Andric    using reference              = _Tp &;
203*0b57cec5SDimitry Andric    using const_reference        = const _Tp &;
204*0b57cec5SDimitry Andric    using iterator               =  __wrap_iter<pointer>;
205*0b57cec5SDimitry Andric    using const_iterator         =  __wrap_iter<const_pointer>;
206*0b57cec5SDimitry Andric    using reverse_iterator       = _VSTD::reverse_iterator<iterator>;
207*0b57cec5SDimitry Andric    using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>;
208*0b57cec5SDimitry Andric
209*0b57cec5SDimitry Andric    static constexpr index_type extent = _Extent;
210*0b57cec5SDimitry Andric
211*0b57cec5SDimitry Andric// [span.cons], span constructors, copy, assignment, and destructor
212*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}
213*0b57cec5SDimitry Andric    { static_assert(_Extent == 0, "Can't default construct a statically sized span with size > 0"); }
214*0b57cec5SDimitry Andric
215*0b57cec5SDimitry Andric    constexpr span           (const span&) noexcept = default;
216*0b57cec5SDimitry Andric    constexpr span& operator=(const span&) noexcept = default;
217*0b57cec5SDimitry Andric
218*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr}
219*0b57cec5SDimitry Andric        { (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); }
220*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}
221*0b57cec5SDimitry Andric        { (void)__l;     _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); }
222*0b57cec5SDimitry Andric
223*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent])          noexcept : __data{__arr} {}
224*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span(      array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {}
225*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span(const array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {}
226*0b57cec5SDimitry Andric
227*0b57cec5SDimitry Andric    template <class _OtherElementType>
228*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
229*0b57cec5SDimitry Andric        constexpr span(const span<_OtherElementType, _Extent>& __other,
230*0b57cec5SDimitry Andric                       enable_if_t<
231*0b57cec5SDimitry Andric                          is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
232*0b57cec5SDimitry Andric                          nullptr_t> = nullptr)
233*0b57cec5SDimitry Andric        : __data{__other.data()} {}
234*0b57cec5SDimitry Andric
235*0b57cec5SDimitry Andric    template <class _OtherElementType>
236*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
237*0b57cec5SDimitry Andric        constexpr span(const span<_OtherElementType, dynamic_extent>& __other,
238*0b57cec5SDimitry Andric                       enable_if_t<
239*0b57cec5SDimitry Andric                          is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
240*0b57cec5SDimitry Andric                          nullptr_t> = nullptr) noexcept
241*0b57cec5SDimitry Andric        : __data{__other.data()} { _LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); }
242*0b57cec5SDimitry Andric
243*0b57cec5SDimitry Andric
244*0b57cec5SDimitry Andric//  ~span() noexcept = default;
245*0b57cec5SDimitry Andric
246*0b57cec5SDimitry Andric    template <size_t _Count>
247*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
248*0b57cec5SDimitry Andric    constexpr span<element_type, _Count> first() const noexcept
249*0b57cec5SDimitry Andric    {
250*0b57cec5SDimitry Andric        static_assert(_Count <= _Extent, "Count out of range in span::first()");
251*0b57cec5SDimitry Andric        return {data(), _Count};
252*0b57cec5SDimitry Andric    }
253*0b57cec5SDimitry Andric
254*0b57cec5SDimitry Andric    template <size_t _Count>
255*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
256*0b57cec5SDimitry Andric    constexpr span<element_type, _Count> last() const noexcept
257*0b57cec5SDimitry Andric    {
258*0b57cec5SDimitry Andric        static_assert(_Count <= _Extent, "Count out of range in span::last()");
259*0b57cec5SDimitry Andric        return {data() + size() - _Count, _Count};
260*0b57cec5SDimitry Andric    }
261*0b57cec5SDimitry Andric
262*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
263*0b57cec5SDimitry Andric    constexpr span<element_type, dynamic_extent> first(index_type __count) const noexcept
264*0b57cec5SDimitry Andric    {
265*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(__count <= size(), "Count out of range in span::first(count)");
266*0b57cec5SDimitry Andric        return {data(), __count};
267*0b57cec5SDimitry Andric    }
268*0b57cec5SDimitry Andric
269*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
270*0b57cec5SDimitry Andric    constexpr span<element_type, dynamic_extent> last(index_type __count) const noexcept
271*0b57cec5SDimitry Andric    {
272*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(__count <= size(), "Count out of range in span::last(count)");
273*0b57cec5SDimitry Andric        return {data() + size() - __count, __count};
274*0b57cec5SDimitry Andric    }
275*0b57cec5SDimitry Andric
276*0b57cec5SDimitry Andric    template <size_t _Offset, size_t _Count = dynamic_extent>
277*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
278*0b57cec5SDimitry Andric    constexpr auto subspan() const noexcept
279*0b57cec5SDimitry Andric        -> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>
280*0b57cec5SDimitry Andric    {
281*0b57cec5SDimitry Andric        static_assert(_Offset <= _Extent, "Offset out of range in span::subspan()");
282*0b57cec5SDimitry Andric        return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
283*0b57cec5SDimitry Andric    }
284*0b57cec5SDimitry Andric
285*0b57cec5SDimitry Andric
286*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
287*0b57cec5SDimitry Andric    constexpr span<element_type, dynamic_extent>
288*0b57cec5SDimitry Andric       subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept
289*0b57cec5SDimitry Andric    {
290*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(__offset <= size(), "Offset out of range in span::subspan(offset, count)");
291*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(__count  <= size() || __count == dynamic_extent, "Count out of range in span::subspan(offset, count)");
292*0b57cec5SDimitry Andric        if (__count == dynamic_extent)
293*0b57cec5SDimitry Andric            return {data() + __offset, size() - __offset};
294*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(__offset <= size() - __count, "count + offset out of range in span::subspan(offset, count)");
295*0b57cec5SDimitry Andric        return {data() + __offset, __count};
296*0b57cec5SDimitry Andric    }
297*0b57cec5SDimitry Andric
298*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr index_type size()       const noexcept { return _Extent; }
299*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return _Extent * sizeof(element_type); }
300*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr bool empty()            const noexcept { return _Extent == 0; }
301*0b57cec5SDimitry Andric
302*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept
303*0b57cec5SDimitry Andric    {
304*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T,N>[] index out of bounds");
305*0b57cec5SDimitry Andric        return __data[__idx];
306*0b57cec5SDimitry Andric    }
307*0b57cec5SDimitry Andric
308*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept
309*0b57cec5SDimitry Andric    {
310*0b57cec5SDimitry Andric        static_assert(_Extent > 0, "span<T,N>[].front() on empty span");
311*0b57cec5SDimitry Andric        return __data[0];
312*0b57cec5SDimitry Andric    }
313*0b57cec5SDimitry Andric
314*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept
315*0b57cec5SDimitry Andric    {
316*0b57cec5SDimitry Andric        static_assert(_Extent > 0, "span<T,N>[].back() on empty span");
317*0b57cec5SDimitry Andric        return __data[size()-1];
318*0b57cec5SDimitry Andric    }
319*0b57cec5SDimitry Andric
320*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr pointer data()                         const noexcept { return __data; }
321*0b57cec5SDimitry Andric
322*0b57cec5SDimitry Andric// [span.iter], span iterator support
323*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr iterator                 begin() const noexcept { return iterator(data()); }
324*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr iterator                   end() const noexcept { return iterator(data() + size()); }
325*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr const_iterator          cbegin() const noexcept { return const_iterator(data()); }
326*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr const_iterator            cend() const noexcept { return const_iterator(data() + size()); }
327*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator        rbegin() const noexcept { return reverse_iterator(end()); }
328*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator          rend() const noexcept { return reverse_iterator(begin()); }
329*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
330*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator   crend() const noexcept { return const_reverse_iterator(cbegin()); }
331*0b57cec5SDimitry Andric
332*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept
333*0b57cec5SDimitry Andric    {
334*0b57cec5SDimitry Andric        pointer __p = __data;
335*0b57cec5SDimitry Andric        __data = __other.__data;
336*0b57cec5SDimitry Andric        __other.__data = __p;
337*0b57cec5SDimitry Andric    }
338*0b57cec5SDimitry Andric
339*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept
340*0b57cec5SDimitry Andric    { return {reinterpret_cast<const byte *>(data()), size_bytes()}; }
341*0b57cec5SDimitry Andric
342*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY span<byte, _Extent * sizeof(element_type)> __as_writable_bytes() const noexcept
343*0b57cec5SDimitry Andric    { return {reinterpret_cast<byte *>(data()), size_bytes()}; }
344*0b57cec5SDimitry Andric
345*0b57cec5SDimitry Andricprivate:
346*0b57cec5SDimitry Andric    pointer    __data;
347*0b57cec5SDimitry Andric
348*0b57cec5SDimitry Andric};
349*0b57cec5SDimitry Andric
350*0b57cec5SDimitry Andric
351*0b57cec5SDimitry Andrictemplate <typename _Tp>
352*0b57cec5SDimitry Andricclass _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> {
353*0b57cec5SDimitry Andricprivate:
354*0b57cec5SDimitry Andric
355*0b57cec5SDimitry Andricpublic:
356*0b57cec5SDimitry Andric//  constants and types
357*0b57cec5SDimitry Andric    using element_type           = _Tp;
358*0b57cec5SDimitry Andric    using value_type             = remove_cv_t<_Tp>;
359*0b57cec5SDimitry Andric    using index_type             = size_t;
360*0b57cec5SDimitry Andric    using difference_type        = ptrdiff_t;
361*0b57cec5SDimitry Andric    using pointer                = _Tp *;
362*0b57cec5SDimitry Andric    using const_pointer          = const _Tp *;
363*0b57cec5SDimitry Andric    using reference              = _Tp &;
364*0b57cec5SDimitry Andric    using const_reference        = const _Tp &;
365*0b57cec5SDimitry Andric    using iterator               =  __wrap_iter<pointer>;
366*0b57cec5SDimitry Andric    using const_iterator         =  __wrap_iter<const_pointer>;
367*0b57cec5SDimitry Andric    using reverse_iterator       = _VSTD::reverse_iterator<iterator>;
368*0b57cec5SDimitry Andric    using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>;
369*0b57cec5SDimitry Andric
370*0b57cec5SDimitry Andric    static constexpr index_type extent = dynamic_extent;
371*0b57cec5SDimitry Andric
372*0b57cec5SDimitry Andric// [span.cons], span constructors, copy, assignment, and destructor
373*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} {}
374*0b57cec5SDimitry Andric
375*0b57cec5SDimitry Andric    constexpr span           (const span&) noexcept = default;
376*0b57cec5SDimitry Andric    constexpr span& operator=(const span&) noexcept = default;
377*0b57cec5SDimitry Andric
378*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr}, __size{__count} {}
379*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{static_cast<size_t>(distance(__f, __l))} {}
380*0b57cec5SDimitry Andric
381*0b57cec5SDimitry Andric    template <size_t _Sz>
382*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
383*0b57cec5SDimitry Andric    constexpr span(element_type (&__arr)[_Sz])          noexcept : __data{__arr}, __size{_Sz} {}
384*0b57cec5SDimitry Andric
385*0b57cec5SDimitry Andric    template <size_t _Sz>
386*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
387*0b57cec5SDimitry Andric    constexpr span(array<value_type, _Sz>& __arr)       noexcept : __data{__arr.data()}, __size{_Sz} {}
388*0b57cec5SDimitry Andric
389*0b57cec5SDimitry Andric    template <size_t _Sz>
390*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
391*0b57cec5SDimitry Andric    constexpr span(const array<value_type, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
392*0b57cec5SDimitry Andric
393*0b57cec5SDimitry Andric    template <class _Container>
394*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
395*0b57cec5SDimitry Andric        constexpr span(      _Container& __c,
396*0b57cec5SDimitry Andric            enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
397*0b57cec5SDimitry Andric        : __data{_VSTD::data(__c)}, __size{(index_type) _VSTD::size(__c)} {}
398*0b57cec5SDimitry Andric
399*0b57cec5SDimitry Andric    template <class _Container>
400*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
401*0b57cec5SDimitry Andric        constexpr span(const _Container& __c,
402*0b57cec5SDimitry Andric            enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
403*0b57cec5SDimitry Andric        : __data{_VSTD::data(__c)}, __size{(index_type) _VSTD::size(__c)} {}
404*0b57cec5SDimitry Andric
405*0b57cec5SDimitry Andric
406*0b57cec5SDimitry Andric    template <class _OtherElementType, size_t _OtherExtent>
407*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
408*0b57cec5SDimitry Andric        constexpr span(const span<_OtherElementType, _OtherExtent>& __other,
409*0b57cec5SDimitry Andric                       enable_if_t<
410*0b57cec5SDimitry Andric                          is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
411*0b57cec5SDimitry Andric                          nullptr_t> = nullptr) noexcept
412*0b57cec5SDimitry Andric        : __data{__other.data()}, __size{__other.size()} {}
413*0b57cec5SDimitry Andric
414*0b57cec5SDimitry Andric//    ~span() noexcept = default;
415*0b57cec5SDimitry Andric
416*0b57cec5SDimitry Andric    template <size_t _Count>
417*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
418*0b57cec5SDimitry Andric    constexpr span<element_type, _Count> first() const noexcept
419*0b57cec5SDimitry Andric    {
420*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()");
421*0b57cec5SDimitry Andric        return {data(), _Count};
422*0b57cec5SDimitry Andric    }
423*0b57cec5SDimitry Andric
424*0b57cec5SDimitry Andric    template <size_t _Count>
425*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
426*0b57cec5SDimitry Andric    constexpr span<element_type, _Count> last() const noexcept
427*0b57cec5SDimitry Andric    {
428*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()");
429*0b57cec5SDimitry Andric        return {data() + size() - _Count, _Count};
430*0b57cec5SDimitry Andric    }
431*0b57cec5SDimitry Andric
432*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
433*0b57cec5SDimitry Andric    constexpr span<element_type, dynamic_extent> first(index_type __count) const noexcept
434*0b57cec5SDimitry Andric    {
435*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(__count <= size(), "Count out of range in span::first(count)");
436*0b57cec5SDimitry Andric        return {data(), __count};
437*0b57cec5SDimitry Andric    }
438*0b57cec5SDimitry Andric
439*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
440*0b57cec5SDimitry Andric    constexpr span<element_type, dynamic_extent> last (index_type __count) const noexcept
441*0b57cec5SDimitry Andric    {
442*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(__count <= size(), "Count out of range in span::last(count)");
443*0b57cec5SDimitry Andric        return {data() + size() - __count, __count};
444*0b57cec5SDimitry Andric    }
445*0b57cec5SDimitry Andric
446*0b57cec5SDimitry Andric    template <size_t _Offset, size_t _Count = dynamic_extent>
447*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
448*0b57cec5SDimitry Andric    constexpr span<_Tp, dynamic_extent> subspan() const noexcept
449*0b57cec5SDimitry Andric    {
450*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(_Offset <= size(), "Offset out of range in span::subspan()");
451*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(_Count == dynamic_extent || _Offset + _Count <= size(), "Count out of range in span::subspan()");
452*0b57cec5SDimitry Andric        return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
453*0b57cec5SDimitry Andric    }
454*0b57cec5SDimitry Andric
455*0b57cec5SDimitry Andric    constexpr span<element_type, dynamic_extent>
456*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY
457*0b57cec5SDimitry Andric    subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept
458*0b57cec5SDimitry Andric    {
459*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(__offset <= size(), "Offset out of range in span::subspan(offset, count)");
460*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(__count  <= size() || __count == dynamic_extent, "count out of range in span::subspan(offset, count)");
461*0b57cec5SDimitry Andric        if (__count == dynamic_extent)
462*0b57cec5SDimitry Andric            return {data() + __offset, size() - __offset};
463*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(__offset <= size() - __count, "Offset + count out of range in span::subspan(offset, count)");
464*0b57cec5SDimitry Andric        return {data() + __offset, __count};
465*0b57cec5SDimitry Andric    }
466*0b57cec5SDimitry Andric
467*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr index_type size()       const noexcept { return __size; }
468*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return __size * sizeof(element_type); }
469*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr bool empty()            const noexcept { return __size == 0; }
470*0b57cec5SDimitry Andric
471*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept
472*0b57cec5SDimitry Andric    {
473*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T>[] index out of bounds");
474*0b57cec5SDimitry Andric        return __data[__idx];
475*0b57cec5SDimitry Andric    }
476*0b57cec5SDimitry Andric
477*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept
478*0b57cec5SDimitry Andric    {
479*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(!empty(), "span<T>[].front() on empty span");
480*0b57cec5SDimitry Andric        return __data[0];
481*0b57cec5SDimitry Andric    }
482*0b57cec5SDimitry Andric
483*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept
484*0b57cec5SDimitry Andric    {
485*0b57cec5SDimitry Andric        _LIBCPP_ASSERT(!empty(), "span<T>[].back() on empty span");
486*0b57cec5SDimitry Andric        return __data[size()-1];
487*0b57cec5SDimitry Andric    }
488*0b57cec5SDimitry Andric
489*0b57cec5SDimitry Andric
490*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr pointer data()                         const noexcept { return __data; }
491*0b57cec5SDimitry Andric
492*0b57cec5SDimitry Andric// [span.iter], span iterator support
493*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr iterator                 begin() const noexcept { return iterator(data()); }
494*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr iterator                   end() const noexcept { return iterator(data() + size()); }
495*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr const_iterator          cbegin() const noexcept { return const_iterator(data()); }
496*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr const_iterator            cend() const noexcept { return const_iterator(data() + size()); }
497*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator        rbegin() const noexcept { return reverse_iterator(end()); }
498*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator          rend() const noexcept { return reverse_iterator(begin()); }
499*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
500*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator   crend() const noexcept { return const_reverse_iterator(cbegin()); }
501*0b57cec5SDimitry Andric
502*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept
503*0b57cec5SDimitry Andric    {
504*0b57cec5SDimitry Andric        pointer __p = __data;
505*0b57cec5SDimitry Andric        __data = __other.__data;
506*0b57cec5SDimitry Andric        __other.__data = __p;
507*0b57cec5SDimitry Andric
508*0b57cec5SDimitry Andric        index_type __sz = __size;
509*0b57cec5SDimitry Andric        __size = __other.__size;
510*0b57cec5SDimitry Andric        __other.__size = __sz;
511*0b57cec5SDimitry Andric    }
512*0b57cec5SDimitry Andric
513*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY span<const byte, dynamic_extent> __as_bytes() const noexcept
514*0b57cec5SDimitry Andric    { return {reinterpret_cast<const byte *>(data()), size_bytes()}; }
515*0b57cec5SDimitry Andric
516*0b57cec5SDimitry Andric    _LIBCPP_INLINE_VISIBILITY span<byte, dynamic_extent> __as_writable_bytes() const noexcept
517*0b57cec5SDimitry Andric    { return {reinterpret_cast<byte *>(data()), size_bytes()}; }
518*0b57cec5SDimitry Andric
519*0b57cec5SDimitry Andricprivate:
520*0b57cec5SDimitry Andric    pointer    __data;
521*0b57cec5SDimitry Andric    index_type __size;
522*0b57cec5SDimitry Andric};
523*0b57cec5SDimitry Andric
524*0b57cec5SDimitry Andric//  tuple interface
525*0b57cec5SDimitry Andrictemplate <class _Tp, size_t _Size>
526*0b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS tuple_size<span<_Tp, _Size>>
527*0b57cec5SDimitry Andric    : public integral_constant<size_t, _Size> {};
528*0b57cec5SDimitry Andric
529*0b57cec5SDimitry Andrictemplate <class _Tp>
530*0b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS tuple_size<span<_Tp, dynamic_extent>>; // declared but not defined
531*0b57cec5SDimitry Andric
532*0b57cec5SDimitry Andric
533*0b57cec5SDimitry Andrictemplate <size_t _Ip, class _Tp, size_t _Size>
534*0b57cec5SDimitry Andricstruct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, span<_Tp, _Size>>
535*0b57cec5SDimitry Andric{
536*0b57cec5SDimitry Andric    static_assert( dynamic_extent != _Size, "std::tuple_element<> not supported for std::span<T, dynamic_extent>");
537*0b57cec5SDimitry Andric    static_assert(_Ip < _Size, "Index out of bounds in std::tuple_element<> (std::span)");
538*0b57cec5SDimitry Andric    typedef _Tp type;
539*0b57cec5SDimitry Andric};
540*0b57cec5SDimitry Andric
541*0b57cec5SDimitry Andrictemplate <size_t _Ip, class _Tp, size_t _Size>
542*0b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY constexpr
543*0b57cec5SDimitry Andric_Tp&
544*0b57cec5SDimitry Andricget(span<_Tp, _Size> __s) noexcept
545*0b57cec5SDimitry Andric{
546*0b57cec5SDimitry Andric    static_assert( dynamic_extent != _Size, "std::get<> not supported for std::span<T, dynamic_extent>");
547*0b57cec5SDimitry Andric    static_assert(_Ip < _Size, "Index out of bounds in std::get<> (std::span)");
548*0b57cec5SDimitry Andric    return __s[_Ip];
549*0b57cec5SDimitry Andric}
550*0b57cec5SDimitry Andric
551*0b57cec5SDimitry Andric
552*0b57cec5SDimitry Andric//  as_bytes & as_writable_bytes
553*0b57cec5SDimitry Andrictemplate <class _Tp, size_t _Extent>
554*0b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
555*0b57cec5SDimitry Andricauto as_bytes(span<_Tp, _Extent> __s) noexcept
556*0b57cec5SDimitry Andric-> decltype(__s.__as_bytes())
557*0b57cec5SDimitry Andric{ return    __s.__as_bytes(); }
558*0b57cec5SDimitry Andric
559*0b57cec5SDimitry Andrictemplate <class _Tp, size_t _Extent>
560*0b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
561*0b57cec5SDimitry Andricauto as_writable_bytes(span<_Tp, _Extent> __s) noexcept
562*0b57cec5SDimitry Andric-> enable_if_t<!is_const_v<_Tp>, decltype(__s.__as_writable_bytes())>
563*0b57cec5SDimitry Andric{ return __s.__as_writable_bytes(); }
564*0b57cec5SDimitry Andric
565*0b57cec5SDimitry Andrictemplate <class _Tp, size_t _Extent>
566*0b57cec5SDimitry Andric_LIBCPP_INLINE_VISIBILITY
567*0b57cec5SDimitry Andricconstexpr void swap(span<_Tp, _Extent> &__lhs, span<_Tp, _Extent> &__rhs) noexcept
568*0b57cec5SDimitry Andric{ __lhs.swap(__rhs); }
569*0b57cec5SDimitry Andric
570*0b57cec5SDimitry Andric
571*0b57cec5SDimitry Andric//  Deduction guides
572*0b57cec5SDimitry Andrictemplate<class _Tp, size_t _Sz>
573*0b57cec5SDimitry Andric    span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>;
574*0b57cec5SDimitry Andric
575*0b57cec5SDimitry Andrictemplate<class _Tp, size_t _Sz>
576*0b57cec5SDimitry Andric    span(array<_Tp, _Sz>&) -> span<_Tp, _Sz>;
577*0b57cec5SDimitry Andric
578*0b57cec5SDimitry Andrictemplate<class _Tp, size_t _Sz>
579*0b57cec5SDimitry Andric    span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>;
580*0b57cec5SDimitry Andric
581*0b57cec5SDimitry Andrictemplate<class _Container>
582*0b57cec5SDimitry Andric    span(_Container&) -> span<typename _Container::value_type>;
583*0b57cec5SDimitry Andric
584*0b57cec5SDimitry Andrictemplate<class _Container>
585*0b57cec5SDimitry Andric    span(const _Container&) -> span<const typename _Container::value_type>;
586*0b57cec5SDimitry Andric
587*0b57cec5SDimitry Andric#endif // _LIBCPP_STD_VER > 17
588*0b57cec5SDimitry Andric
589*0b57cec5SDimitry Andric_LIBCPP_END_NAMESPACE_STD
590*0b57cec5SDimitry Andric
591*0b57cec5SDimitry Andric#endif // _LIBCPP_SPAN
592