xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/std/span (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1fb8a8121Smrg// Components for manipulating non-owning sequences of objects -*- C++ -*-
2fb8a8121Smrg
3*b1e83836Smrg// Copyright (C) 2019-2022 Free Software Foundation, Inc.
4fb8a8121Smrg//
5fb8a8121Smrg// This file is part of the GNU ISO C++ Library.  This library is free
6fb8a8121Smrg// software; you can redistribute it and/or modify it under the
7fb8a8121Smrg// terms of the GNU General Public License as published by the
8fb8a8121Smrg// Free Software Foundation; either version 3, or (at your option)
9fb8a8121Smrg// any later version.
10fb8a8121Smrg
11fb8a8121Smrg// This library is distributed in the hope that it will be useful,
12fb8a8121Smrg// but WITHOUT ANY WARRANTY; without even the implied warranty of
13fb8a8121Smrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14fb8a8121Smrg// GNU General Public License for more details.
15fb8a8121Smrg
16fb8a8121Smrg// Under Section 7 of GPL version 3, you are granted additional
17fb8a8121Smrg// permissions described in the GCC Runtime Library Exception, version
18fb8a8121Smrg// 3.1, as published by the Free Software Foundation.
19fb8a8121Smrg
20fb8a8121Smrg// You should have received a copy of the GNU General Public License and
21fb8a8121Smrg// a copy of the GCC Runtime Library Exception along with this program;
22fb8a8121Smrg// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23fb8a8121Smrg// <http://www.gnu.org/licenses/>.
24fb8a8121Smrg
25fb8a8121Smrg/** @file span
26fb8a8121Smrg *  This is a Standard C++ Library header.
27fb8a8121Smrg */
28fb8a8121Smrg
29fb8a8121Smrg//
30fb8a8121Smrg// P0122 span library
31fb8a8121Smrg// Contributed by ThePhD
32fb8a8121Smrg//
33fb8a8121Smrg
34fb8a8121Smrg#ifndef _GLIBCXX_SPAN
35fb8a8121Smrg#define _GLIBCXX_SPAN 1
36fb8a8121Smrg
37fb8a8121Smrg#pragma GCC system_header
38fb8a8121Smrg
39fb8a8121Smrg#if __cplusplus > 201703L
40fb8a8121Smrg
41fb8a8121Smrg#include <array>
42*b1e83836Smrg#include <cstddef>
43fb8a8121Smrg#include <bits/stl_iterator.h>
44*b1e83836Smrg#include <bits/ranges_base.h>
45fb8a8121Smrg
46fb8a8121Smrg#if __cpp_lib_concepts
47fb8a8121Smrgnamespace std _GLIBCXX_VISIBILITY(default)
48fb8a8121Smrg{
49fb8a8121Smrg_GLIBCXX_BEGIN_NAMESPACE_VERSION
50fb8a8121Smrg
51fb8a8121Smrg#define __cpp_lib_span 202002L
52fb8a8121Smrg
53fb8a8121Smrg  inline constexpr size_t dynamic_extent = static_cast<size_t>(-1);
54fb8a8121Smrg
55fb8a8121Smrg  template<typename _Type, size_t _Extent>
56fb8a8121Smrg    class span;
57fb8a8121Smrg
58fb8a8121Smrg  namespace __detail
59fb8a8121Smrg  {
60fb8a8121Smrg    template<typename _Tp>
61*b1e83836Smrg      inline constexpr bool __is_span = false;
62fb8a8121Smrg
63fb8a8121Smrg    template<typename _Tp, size_t _Num>
64*b1e83836Smrg      inline constexpr bool __is_span<span<_Tp, _Num>> = true;
65fb8a8121Smrg
66fb8a8121Smrg    template<typename _Tp>
67*b1e83836Smrg      inline constexpr bool __is_std_array = false;
68fb8a8121Smrg
69fb8a8121Smrg    template<typename _Tp, size_t _Num>
70*b1e83836Smrg      inline constexpr bool __is_std_array<std::array<_Tp, _Num>> = true;
71fb8a8121Smrg
72fb8a8121Smrg    template<size_t _Extent>
73fb8a8121Smrg      class __extent_storage
74fb8a8121Smrg      {
75fb8a8121Smrg      public:
76fb8a8121Smrg	constexpr
77fb8a8121Smrg	__extent_storage(size_t) noexcept
78fb8a8121Smrg	{ }
79fb8a8121Smrg
80fb8a8121Smrg	static constexpr size_t
81fb8a8121Smrg	_M_extent() noexcept
82fb8a8121Smrg	{ return _Extent; }
83fb8a8121Smrg      };
84fb8a8121Smrg
85fb8a8121Smrg    template<>
86fb8a8121Smrg      class __extent_storage<dynamic_extent>
87fb8a8121Smrg      {
88fb8a8121Smrg      public:
89fb8a8121Smrg	constexpr
90fb8a8121Smrg	__extent_storage(size_t __extent) noexcept
91fb8a8121Smrg	: _M_extent_value(__extent)
92fb8a8121Smrg	{ }
93fb8a8121Smrg
94fb8a8121Smrg	constexpr size_t
95fb8a8121Smrg	_M_extent() const noexcept
96fb8a8121Smrg	{ return this->_M_extent_value; }
97fb8a8121Smrg
98fb8a8121Smrg      private:
99fb8a8121Smrg	size_t _M_extent_value;
100fb8a8121Smrg      };
101fb8a8121Smrg  } // namespace __detail
102fb8a8121Smrg
103fb8a8121Smrg  template<typename _Type, size_t _Extent = dynamic_extent>
104fb8a8121Smrg    class span
105fb8a8121Smrg    {
106fb8a8121Smrg      template<size_t _Offset, size_t _Count>
107fb8a8121Smrg	static constexpr size_t
108fb8a8121Smrg	_S_subspan_extent()
109fb8a8121Smrg	{
110fb8a8121Smrg	  if constexpr (_Count != dynamic_extent)
111fb8a8121Smrg	    return _Count;
112fb8a8121Smrg	  else if constexpr (extent != dynamic_extent)
113fb8a8121Smrg	    return _Extent - _Offset;
114fb8a8121Smrg	  else
115fb8a8121Smrg	    return dynamic_extent;
116fb8a8121Smrg	}
117fb8a8121Smrg
118fb8a8121Smrg      // _GLIBCXX_RESOLVE_LIB_DEFECTS
119fb8a8121Smrg      // 3255. span's array constructor is too strict
120fb8a8121Smrg      template<typename _Tp, size_t _ArrayExtent>
121fb8a8121Smrg	requires (_Extent == dynamic_extent || _ArrayExtent == _Extent)
122fb8a8121Smrg	using __is_compatible_array = __is_array_convertible<_Type, _Tp>;
123fb8a8121Smrg
124fb8a8121Smrg      template<typename _Ref>
125fb8a8121Smrg	using __is_compatible_ref
126fb8a8121Smrg	  = __is_array_convertible<_Type, remove_reference_t<_Ref>>;
127fb8a8121Smrg
128fb8a8121Smrg    public:
129fb8a8121Smrg      // member types
130fb8a8121Smrg      using element_type           = _Type;
131fb8a8121Smrg      using value_type             = remove_cv_t<_Type>;
132fb8a8121Smrg      using size_type              = size_t;
133fb8a8121Smrg      using difference_type        = ptrdiff_t;
134fb8a8121Smrg      using pointer                = _Type*;
135fb8a8121Smrg      using const_pointer          = const _Type*;
136fb8a8121Smrg      using reference              = element_type&;
137fb8a8121Smrg      using const_reference        = const element_type&;
138fb8a8121Smrg      using iterator = __gnu_cxx::__normal_iterator<pointer, span>;
139fb8a8121Smrg      using reverse_iterator       = std::reverse_iterator<iterator>;
140fb8a8121Smrg
141fb8a8121Smrg      // member constants
142fb8a8121Smrg      static constexpr size_t extent = _Extent;
143fb8a8121Smrg
144fb8a8121Smrg      // constructors, copy and assignment
145fb8a8121Smrg
146fb8a8121Smrg      constexpr
147fb8a8121Smrg      span() noexcept
148fb8a8121Smrg      requires ((_Extent + 1u) <= 1u)
149*b1e83836Smrg      : _M_ptr(nullptr), _M_extent(0)
150fb8a8121Smrg      { }
151fb8a8121Smrg
152fb8a8121Smrg      template<contiguous_iterator _It>
153fb8a8121Smrg	requires __is_compatible_ref<iter_reference_t<_It>>::value
154fb8a8121Smrg	constexpr explicit(extent != dynamic_extent)
155fb8a8121Smrg	span(_It __first, size_type __count)
156fb8a8121Smrg	noexcept
157*b1e83836Smrg	: _M_ptr(std::to_address(__first)), _M_extent(__count)
158fb8a8121Smrg	{
159fb8a8121Smrg	  if constexpr (_Extent != dynamic_extent)
160fb8a8121Smrg	    {
161fb8a8121Smrg	      __glibcxx_assert(__count == _Extent);
162fb8a8121Smrg	    }
1637d4dc15bSmrg	  __glibcxx_requires_valid_range(__first, __first + __count);
164fb8a8121Smrg	}
165fb8a8121Smrg
166fb8a8121Smrg      template<contiguous_iterator _It, sized_sentinel_for<_It> _End>
167fb8a8121Smrg	requires __is_compatible_ref<iter_reference_t<_It>>::value
168fb8a8121Smrg	  && (!is_convertible_v<_End, size_type>)
169fb8a8121Smrg	constexpr explicit(extent != dynamic_extent)
170fb8a8121Smrg	span(_It __first, _End __last)
171fb8a8121Smrg	noexcept(noexcept(__last - __first))
172*b1e83836Smrg	: _M_ptr(std::to_address(__first)),
173*b1e83836Smrg	  _M_extent(static_cast<size_type>(__last - __first))
174fb8a8121Smrg	{
175fb8a8121Smrg	  if constexpr (_Extent != dynamic_extent)
176fb8a8121Smrg	    {
177fb8a8121Smrg	      __glibcxx_assert((__last - __first) == _Extent);
178fb8a8121Smrg	    }
1797d4dc15bSmrg	  __glibcxx_requires_valid_range(__first, __last);
180fb8a8121Smrg	}
181fb8a8121Smrg
182fb8a8121Smrg      template<size_t _ArrayExtent>
183fb8a8121Smrg	requires (_Extent == dynamic_extent || _ArrayExtent == _Extent)
184fb8a8121Smrg	constexpr
185fb8a8121Smrg	span(type_identity_t<element_type> (&__arr)[_ArrayExtent]) noexcept
186fb8a8121Smrg	: span(static_cast<pointer>(__arr), _ArrayExtent)
187fb8a8121Smrg	{ }
188fb8a8121Smrg
189fb8a8121Smrg      template<typename _Tp, size_t _ArrayExtent>
190fb8a8121Smrg	requires __is_compatible_array<_Tp, _ArrayExtent>::value
191fb8a8121Smrg	constexpr
192fb8a8121Smrg	span(array<_Tp, _ArrayExtent>& __arr) noexcept
193fb8a8121Smrg	: span(static_cast<pointer>(__arr.data()), _ArrayExtent)
194fb8a8121Smrg	{ }
195fb8a8121Smrg
196fb8a8121Smrg      template<typename _Tp, size_t _ArrayExtent>
197fb8a8121Smrg	requires __is_compatible_array<const _Tp, _ArrayExtent>::value
198fb8a8121Smrg	constexpr
199fb8a8121Smrg	span(const array<_Tp, _ArrayExtent>& __arr) noexcept
200fb8a8121Smrg	: span(static_cast<pointer>(__arr.data()), _ArrayExtent)
201fb8a8121Smrg	{ }
202fb8a8121Smrg
203fb8a8121Smrg      template<typename _Range>
204*b1e83836Smrg	requires (!__detail::__is_span<remove_cvref_t<_Range>>)
205*b1e83836Smrg	  && (!__detail::__is_std_array<remove_cvref_t<_Range>>)
206fb8a8121Smrg	  && (!is_array_v<remove_cvref_t<_Range>>)
207a448f87cSmrg	  && ranges::contiguous_range<_Range> && ranges::sized_range<_Range>
208a448f87cSmrg	  && (ranges::borrowed_range<_Range> || is_const_v<element_type>)
209fb8a8121Smrg	  && __is_compatible_ref<ranges::range_reference_t<_Range>>::value
210fb8a8121Smrg	constexpr explicit(extent != dynamic_extent)
211fb8a8121Smrg	span(_Range&& __range)
212fb8a8121Smrg	noexcept(noexcept(ranges::data(__range))
213fb8a8121Smrg		  && noexcept(ranges::size(__range)))
214fb8a8121Smrg	: span(ranges::data(__range), ranges::size(__range))
215fb8a8121Smrg	{
216fb8a8121Smrg	  if constexpr (extent != dynamic_extent)
217fb8a8121Smrg	    {
218fb8a8121Smrg	      __glibcxx_assert(ranges::size(__range) == extent);
219fb8a8121Smrg	    }
220fb8a8121Smrg	}
221fb8a8121Smrg
222fb8a8121Smrg      constexpr
223fb8a8121Smrg      span(const span&) noexcept = default;
224fb8a8121Smrg
225fb8a8121Smrg      template<typename _OType, size_t _OExtent>
226fb8a8121Smrg	requires (_Extent == dynamic_extent || _OExtent == dynamic_extent
227fb8a8121Smrg		  || _Extent == _OExtent)
228fb8a8121Smrg	  && (__is_array_convertible<_Type, _OType>::value)
229fb8a8121Smrg	constexpr
230fb8a8121Smrg	explicit(extent != dynamic_extent && _OExtent == dynamic_extent)
231fb8a8121Smrg	span(const span<_OType, _OExtent>& __s) noexcept
232fb8a8121Smrg	: _M_extent(__s.size()), _M_ptr(__s.data())
233fb8a8121Smrg	{
234fb8a8121Smrg	  if constexpr (extent != dynamic_extent)
235fb8a8121Smrg	    {
236fb8a8121Smrg	      __glibcxx_assert(__s.size() == extent);
237fb8a8121Smrg	    }
238fb8a8121Smrg	}
239fb8a8121Smrg
240fb8a8121Smrg      ~span() noexcept = default;
241fb8a8121Smrg
242fb8a8121Smrg      constexpr span&
243fb8a8121Smrg      operator=(const span&) noexcept = default;
244fb8a8121Smrg
245fb8a8121Smrg      // observers
246fb8a8121Smrg
247fb8a8121Smrg      constexpr size_type
248fb8a8121Smrg      size() const noexcept
249fb8a8121Smrg      { return this->_M_extent._M_extent(); }
250fb8a8121Smrg
251fb8a8121Smrg      constexpr size_type
252fb8a8121Smrg      size_bytes() const noexcept
253fb8a8121Smrg      { return this->_M_extent._M_extent() * sizeof(element_type); }
254fb8a8121Smrg
255fb8a8121Smrg      [[nodiscard]] constexpr bool
256fb8a8121Smrg      empty() const noexcept
257fb8a8121Smrg      { return size() == 0; }
258fb8a8121Smrg
259fb8a8121Smrg      // element access
260fb8a8121Smrg
261fb8a8121Smrg      constexpr reference
262fb8a8121Smrg      front() const noexcept
263fb8a8121Smrg      {
264fb8a8121Smrg	__glibcxx_assert(!empty());
265fb8a8121Smrg	return *this->_M_ptr;
266fb8a8121Smrg      }
267fb8a8121Smrg
268fb8a8121Smrg      constexpr reference
269fb8a8121Smrg      back() const noexcept
270fb8a8121Smrg      {
271fb8a8121Smrg	__glibcxx_assert(!empty());
272fb8a8121Smrg	return *(this->_M_ptr + (size() - 1));
273fb8a8121Smrg      }
274fb8a8121Smrg
275fb8a8121Smrg      constexpr reference
276fb8a8121Smrg      operator[](size_type __idx) const noexcept
277fb8a8121Smrg      {
278fb8a8121Smrg	__glibcxx_assert(__idx < size());
279fb8a8121Smrg	return *(this->_M_ptr + __idx);
280fb8a8121Smrg      }
281fb8a8121Smrg
282fb8a8121Smrg      constexpr pointer
283fb8a8121Smrg      data() const noexcept
284fb8a8121Smrg      { return this->_M_ptr; }
285fb8a8121Smrg
286fb8a8121Smrg      // iterator support
287fb8a8121Smrg
288fb8a8121Smrg      constexpr iterator
289fb8a8121Smrg      begin() const noexcept
290fb8a8121Smrg      { return iterator(this->_M_ptr); }
291fb8a8121Smrg
292fb8a8121Smrg      constexpr iterator
293fb8a8121Smrg      end() const noexcept
294fb8a8121Smrg      { return iterator(this->_M_ptr + this->size()); }
295fb8a8121Smrg
296fb8a8121Smrg      constexpr reverse_iterator
297fb8a8121Smrg      rbegin() const noexcept
298fb8a8121Smrg      { return reverse_iterator(this->end()); }
299fb8a8121Smrg
300fb8a8121Smrg      constexpr reverse_iterator
301fb8a8121Smrg      rend() const noexcept
302fb8a8121Smrg      { return reverse_iterator(this->begin()); }
303fb8a8121Smrg
304fb8a8121Smrg      // subviews
305fb8a8121Smrg
306fb8a8121Smrg      template<size_t _Count>
307fb8a8121Smrg	constexpr span<element_type, _Count>
308fb8a8121Smrg	first() const noexcept
309fb8a8121Smrg	{
310fb8a8121Smrg	  if constexpr (_Extent == dynamic_extent)
311fb8a8121Smrg	    __glibcxx_assert(_Count <= size());
312fb8a8121Smrg	  else
313fb8a8121Smrg	    static_assert(_Count <= extent);
314fb8a8121Smrg	  using _Sp = span<element_type, _Count>;
315fb8a8121Smrg	  return _Sp{ this->data(), _Count };
316fb8a8121Smrg	}
317fb8a8121Smrg
318fb8a8121Smrg      constexpr span<element_type, dynamic_extent>
319fb8a8121Smrg      first(size_type __count) const noexcept
320fb8a8121Smrg      {
321fb8a8121Smrg	__glibcxx_assert(__count <= size());
322fb8a8121Smrg	return { this->data(), __count };
323fb8a8121Smrg      }
324fb8a8121Smrg
325fb8a8121Smrg      template<size_t _Count>
326fb8a8121Smrg	constexpr span<element_type, _Count>
327fb8a8121Smrg	last() const noexcept
328fb8a8121Smrg	{
329fb8a8121Smrg	  if constexpr (_Extent == dynamic_extent)
330fb8a8121Smrg	    __glibcxx_assert(_Count <= size());
331fb8a8121Smrg	  else
332fb8a8121Smrg	    static_assert(_Count <= extent);
333fb8a8121Smrg	  using _Sp = span<element_type, _Count>;
334fb8a8121Smrg	  return _Sp{ this->data() + (this->size() - _Count), _Count };
335fb8a8121Smrg	}
336fb8a8121Smrg
337fb8a8121Smrg      constexpr span<element_type, dynamic_extent>
338fb8a8121Smrg      last(size_type __count) const noexcept
339fb8a8121Smrg      {
340fb8a8121Smrg	__glibcxx_assert(__count <= size());
341fb8a8121Smrg	return { this->data() + (this->size() - __count), __count };
342fb8a8121Smrg      }
343fb8a8121Smrg
344fb8a8121Smrg      template<size_t _Offset, size_t _Count = dynamic_extent>
345fb8a8121Smrg	constexpr auto
346fb8a8121Smrg	subspan() const noexcept
347fb8a8121Smrg	-> span<element_type, _S_subspan_extent<_Offset, _Count>()>
348fb8a8121Smrg	{
349fb8a8121Smrg	  if constexpr (_Extent == dynamic_extent)
350fb8a8121Smrg	    {
351fb8a8121Smrg	      __glibcxx_assert(_Offset <= size());
352fb8a8121Smrg	    }
353fb8a8121Smrg	  else
354fb8a8121Smrg	    static_assert(_Offset <= extent);
355fb8a8121Smrg
356fb8a8121Smrg	  using _Sp = span<element_type, _S_subspan_extent<_Offset, _Count>()>;
357fb8a8121Smrg
358fb8a8121Smrg	  if constexpr (_Count == dynamic_extent)
359fb8a8121Smrg	    return _Sp{ this->data() + _Offset, this->size() - _Offset };
360fb8a8121Smrg	  else
361fb8a8121Smrg	    {
362fb8a8121Smrg	      if constexpr (_Extent == dynamic_extent)
363fb8a8121Smrg		{
364fb8a8121Smrg		  __glibcxx_assert(_Count <= size());
365fb8a8121Smrg		  __glibcxx_assert(_Count <= (size() - _Offset));
366fb8a8121Smrg		}
367fb8a8121Smrg	      else
368fb8a8121Smrg		{
369fb8a8121Smrg		  static_assert(_Count <= extent);
370fb8a8121Smrg		  static_assert(_Count <= (extent - _Offset));
371fb8a8121Smrg		}
372fb8a8121Smrg	      return _Sp{ this->data() + _Offset, _Count };
373fb8a8121Smrg	    }
374fb8a8121Smrg	}
375fb8a8121Smrg
376fb8a8121Smrg      constexpr span<element_type, dynamic_extent>
377fb8a8121Smrg      subspan(size_type __offset, size_type __count = dynamic_extent) const
378fb8a8121Smrg      noexcept
379fb8a8121Smrg      {
380fb8a8121Smrg	__glibcxx_assert(__offset <= size());
381fb8a8121Smrg	if (__count == dynamic_extent)
382fb8a8121Smrg	  __count = this->size() - __offset;
383fb8a8121Smrg	else
384fb8a8121Smrg	  {
385fb8a8121Smrg	    __glibcxx_assert(__count <= size());
386fb8a8121Smrg	    __glibcxx_assert(__offset + __count <= size());
387fb8a8121Smrg	  }
388fb8a8121Smrg	return {this->data() + __offset, __count};
389fb8a8121Smrg      }
390fb8a8121Smrg
391fb8a8121Smrg    private:
392fb8a8121Smrg      pointer _M_ptr;
393*b1e83836Smrg      [[no_unique_address]] __detail::__extent_storage<extent> _M_extent;
394fb8a8121Smrg    };
395fb8a8121Smrg
396fb8a8121Smrg  // deduction guides
397fb8a8121Smrg
398fb8a8121Smrg  template<typename _Type, size_t _ArrayExtent>
399fb8a8121Smrg    span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>;
400fb8a8121Smrg
401fb8a8121Smrg  template<typename _Type, size_t _ArrayExtent>
402fb8a8121Smrg    span(array<_Type, _ArrayExtent>&) -> span<_Type, _ArrayExtent>;
403fb8a8121Smrg
404fb8a8121Smrg  template<typename _Type, size_t _ArrayExtent>
405fb8a8121Smrg    span(const array<_Type, _ArrayExtent>&)
406fb8a8121Smrg      -> span<const _Type, _ArrayExtent>;
407fb8a8121Smrg
408fb8a8121Smrg  template<contiguous_iterator _Iter, typename _End>
409fb8a8121Smrg    span(_Iter, _End)
410fb8a8121Smrg      -> span<remove_reference_t<iter_reference_t<_Iter>>>;
411fb8a8121Smrg
412a448f87cSmrg  template<ranges::contiguous_range _Range>
413fb8a8121Smrg    span(_Range &&)
414fb8a8121Smrg      -> span<remove_reference_t<ranges::range_reference_t<_Range&>>>;
415fb8a8121Smrg
416fb8a8121Smrg  template<typename _Type, size_t _Extent>
417fb8a8121Smrg    inline
418fb8a8121Smrg    span<const byte, _Extent == dynamic_extent
419fb8a8121Smrg	? dynamic_extent : _Extent * sizeof(_Type)>
420fb8a8121Smrg    as_bytes(span<_Type, _Extent> __sp) noexcept
421fb8a8121Smrg    {
422fb8a8121Smrg      auto data = reinterpret_cast<const byte*>(__sp.data());
423fb8a8121Smrg      auto size = __sp.size_bytes();
424fb8a8121Smrg      constexpr auto extent = _Extent == dynamic_extent
425fb8a8121Smrg	? dynamic_extent : _Extent * sizeof(_Type);
426fb8a8121Smrg      return span<const byte, extent>{data, size};
427fb8a8121Smrg    }
428fb8a8121Smrg
429fb8a8121Smrg  template<typename _Type, size_t _Extent>
430a448f87cSmrg    requires (!is_const_v<_Type>)
431fb8a8121Smrg    inline
432fb8a8121Smrg    span<byte, _Extent == dynamic_extent
433fb8a8121Smrg       ? dynamic_extent : _Extent * sizeof(_Type)>
434fb8a8121Smrg    as_writable_bytes(span<_Type, _Extent> __sp) noexcept
435fb8a8121Smrg    {
436fb8a8121Smrg      auto data = reinterpret_cast<byte*>(__sp.data());
437fb8a8121Smrg      auto size = __sp.size_bytes();
438fb8a8121Smrg      constexpr auto extent = _Extent == dynamic_extent
439fb8a8121Smrg	? dynamic_extent : _Extent * sizeof(_Type);
440fb8a8121Smrg      return span<byte, extent>{data, size};
441fb8a8121Smrg    }
442fb8a8121Smrg
443fb8a8121Smrg  namespace ranges
444fb8a8121Smrg  {
445fb8a8121Smrg    // Opt-in to borrowed_range concept
446fb8a8121Smrg    template<typename _ElementType, size_t _Extent>
447fb8a8121Smrg      inline constexpr bool
448fb8a8121Smrg	enable_borrowed_range<span<_ElementType, _Extent>> = true;
449fb8a8121Smrg
450fb8a8121Smrg    // Opt-in to view concept
451fb8a8121Smrg    template<typename _ElementType, size_t _Extent>
452fb8a8121Smrg      inline constexpr bool
453a448f87cSmrg	enable_view<span<_ElementType, _Extent>> = true;
454fb8a8121Smrg  }
455fb8a8121Smrg_GLIBCXX_END_NAMESPACE_VERSION
456fb8a8121Smrg} // namespace std
457fb8a8121Smrg#endif // concepts
458fb8a8121Smrg#endif // C++20
459fb8a8121Smrg#endif // _GLIBCXX_SPAN
460