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