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