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