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