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