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