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