14c3eb207Smrg// Components for manipulating non-owning sequences of objects -*- C++ -*- 24c3eb207Smrg 34c3eb207Smrg// Copyright (C) 2019-2020 Free Software Foundation, Inc. 44c3eb207Smrg// 54c3eb207Smrg// This file is part of the GNU ISO C++ Library. This library is free 64c3eb207Smrg// software; you can redistribute it and/or modify it under the 74c3eb207Smrg// terms of the GNU General Public License as published by the 84c3eb207Smrg// Free Software Foundation; either version 3, or (at your option) 94c3eb207Smrg// any later version. 104c3eb207Smrg 114c3eb207Smrg// This library is distributed in the hope that it will be useful, 124c3eb207Smrg// but WITHOUT ANY WARRANTY; without even the implied warranty of 134c3eb207Smrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 144c3eb207Smrg// GNU General Public License for more details. 154c3eb207Smrg 164c3eb207Smrg// Under Section 7 of GPL version 3, you are granted additional 174c3eb207Smrg// permissions described in the GCC Runtime Library Exception, version 184c3eb207Smrg// 3.1, as published by the Free Software Foundation. 194c3eb207Smrg 204c3eb207Smrg// You should have received a copy of the GNU General Public License and 214c3eb207Smrg// a copy of the GCC Runtime Library Exception along with this program; 224c3eb207Smrg// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 234c3eb207Smrg// <http://www.gnu.org/licenses/>. 244c3eb207Smrg 254c3eb207Smrg/** @file span 264c3eb207Smrg * This is a Standard C++ Library header. 274c3eb207Smrg */ 284c3eb207Smrg 294c3eb207Smrg// 304c3eb207Smrg// P0122 span library 314c3eb207Smrg// Contributed by ThePhD 324c3eb207Smrg// 334c3eb207Smrg 344c3eb207Smrg#ifndef _GLIBCXX_SPAN 354c3eb207Smrg#define _GLIBCXX_SPAN 1 364c3eb207Smrg 374c3eb207Smrg#pragma GCC system_header 384c3eb207Smrg 394c3eb207Smrg#if __cplusplus > 201703L 404c3eb207Smrg 414c3eb207Smrg#include <type_traits> 424c3eb207Smrg#include <array> 434c3eb207Smrg#include <bits/stl_iterator.h> 444c3eb207Smrg#include <bits/range_access.h> 454c3eb207Smrg 464c3eb207Smrg#if __cpp_lib_concepts 474c3eb207Smrgnamespace std _GLIBCXX_VISIBILITY(default) 484c3eb207Smrg{ 494c3eb207Smrg_GLIBCXX_BEGIN_NAMESPACE_VERSION 504c3eb207Smrg 514c3eb207Smrg#define __cpp_lib_span 202002L 524c3eb207Smrg 534c3eb207Smrg inline constexpr size_t dynamic_extent = static_cast<size_t>(-1); 544c3eb207Smrg 554c3eb207Smrg template<typename _Type, size_t _Extent> 564c3eb207Smrg class span; 574c3eb207Smrg 584c3eb207Smrg namespace __detail 594c3eb207Smrg { 604c3eb207Smrg template<typename _Tp> 614c3eb207Smrg struct __is_std_span : false_type { }; 624c3eb207Smrg 634c3eb207Smrg template<typename _Tp, size_t _Num> 644c3eb207Smrg struct __is_std_span<span<_Tp, _Num>> : true_type { }; 654c3eb207Smrg 664c3eb207Smrg template<typename _Tp> 674c3eb207Smrg struct __is_std_array : false_type { }; 684c3eb207Smrg 694c3eb207Smrg template<typename _Tp, size_t _Num> 704c3eb207Smrg struct __is_std_array<_GLIBCXX_STD_C::array<_Tp, _Num>> : true_type { }; 714c3eb207Smrg 724c3eb207Smrg#ifdef _GLIBCXX_DEBUG 734c3eb207Smrg template<typename _Tp, size_t _Num> 744c3eb207Smrg struct __is_std_array<__debug::array<_Tp, _Num>> : true_type { }; 754c3eb207Smrg#endif 764c3eb207Smrg 774c3eb207Smrg template<size_t _Extent> 784c3eb207Smrg class __extent_storage 794c3eb207Smrg { 804c3eb207Smrg public: 814c3eb207Smrg constexpr 824c3eb207Smrg __extent_storage(size_t) noexcept 834c3eb207Smrg { } 844c3eb207Smrg 854c3eb207Smrg static constexpr size_t 864c3eb207Smrg _M_extent() noexcept 874c3eb207Smrg { return _Extent; } 884c3eb207Smrg }; 894c3eb207Smrg 904c3eb207Smrg template<> 914c3eb207Smrg class __extent_storage<dynamic_extent> 924c3eb207Smrg { 934c3eb207Smrg public: 944c3eb207Smrg constexpr 954c3eb207Smrg __extent_storage(size_t __extent) noexcept 964c3eb207Smrg : _M_extent_value(__extent) 974c3eb207Smrg { } 984c3eb207Smrg 994c3eb207Smrg constexpr size_t 1004c3eb207Smrg _M_extent() const noexcept 1014c3eb207Smrg { return this->_M_extent_value; } 1024c3eb207Smrg 1034c3eb207Smrg private: 1044c3eb207Smrg size_t _M_extent_value; 1054c3eb207Smrg }; 1064c3eb207Smrg } // namespace __detail 1074c3eb207Smrg 1084c3eb207Smrg template<typename _Type, size_t _Extent = dynamic_extent> 1094c3eb207Smrg class span 1104c3eb207Smrg { 1114c3eb207Smrg template<size_t _Offset, size_t _Count> 1124c3eb207Smrg static constexpr size_t 1134c3eb207Smrg _S_subspan_extent() 1144c3eb207Smrg { 1154c3eb207Smrg if constexpr (_Count != dynamic_extent) 1164c3eb207Smrg return _Count; 1174c3eb207Smrg else if constexpr (extent != dynamic_extent) 1184c3eb207Smrg return _Extent - _Offset; 1194c3eb207Smrg else 1204c3eb207Smrg return dynamic_extent; 1214c3eb207Smrg } 1224c3eb207Smrg 1234c3eb207Smrg // _GLIBCXX_RESOLVE_LIB_DEFECTS 1244c3eb207Smrg // 3255. span's array constructor is too strict 1254c3eb207Smrg template<typename _Tp, size_t _ArrayExtent> 1264c3eb207Smrg requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) 1274c3eb207Smrg using __is_compatible_array = __is_array_convertible<_Type, _Tp>; 1284c3eb207Smrg 1294c3eb207Smrg template<typename _Ref> 1304c3eb207Smrg using __is_compatible_ref 1314c3eb207Smrg = __is_array_convertible<_Type, remove_reference_t<_Ref>>; 1324c3eb207Smrg 1334c3eb207Smrg public: 1344c3eb207Smrg // member types 1354c3eb207Smrg using element_type = _Type; 1364c3eb207Smrg using value_type = remove_cv_t<_Type>; 1374c3eb207Smrg using size_type = size_t; 1384c3eb207Smrg using difference_type = ptrdiff_t; 1394c3eb207Smrg using pointer = _Type*; 1404c3eb207Smrg using const_pointer = const _Type*; 1414c3eb207Smrg using reference = element_type&; 1424c3eb207Smrg using const_reference = const element_type&; 1434c3eb207Smrg using iterator = __gnu_cxx::__normal_iterator<pointer, span>; 1444c3eb207Smrg using reverse_iterator = std::reverse_iterator<iterator>; 1454c3eb207Smrg 1464c3eb207Smrg // member constants 1474c3eb207Smrg static constexpr size_t extent = _Extent; 1484c3eb207Smrg 1494c3eb207Smrg // constructors, copy and assignment 1504c3eb207Smrg 1514c3eb207Smrg constexpr 1524c3eb207Smrg span() noexcept 1534c3eb207Smrg requires ((_Extent + 1u) <= 1u) 1544c3eb207Smrg : _M_extent(0), _M_ptr(nullptr) 1554c3eb207Smrg { } 1564c3eb207Smrg 1574c3eb207Smrg template<contiguous_iterator _It> 1584c3eb207Smrg requires __is_compatible_ref<iter_reference_t<_It>>::value 1594c3eb207Smrg constexpr explicit(extent != dynamic_extent) 1604c3eb207Smrg span(_It __first, size_type __count) 1614c3eb207Smrg noexcept 1624c3eb207Smrg : _M_extent(__count), _M_ptr(std::to_address(__first)) 1634c3eb207Smrg { 1644c3eb207Smrg if constexpr (_Extent != dynamic_extent) 1654c3eb207Smrg { 1664c3eb207Smrg __glibcxx_assert(__count == _Extent); 1674c3eb207Smrg } 168*4ac76180Smrg __glibcxx_requires_valid_range(__first, __first + __count); 1694c3eb207Smrg } 1704c3eb207Smrg 1714c3eb207Smrg template<contiguous_iterator _It, sized_sentinel_for<_It> _End> 1724c3eb207Smrg requires __is_compatible_ref<iter_reference_t<_It>>::value 1734c3eb207Smrg && (!is_convertible_v<_End, size_type>) 1744c3eb207Smrg constexpr explicit(extent != dynamic_extent) 1754c3eb207Smrg span(_It __first, _End __last) 1764c3eb207Smrg noexcept(noexcept(__last - __first)) 1774c3eb207Smrg : _M_extent(static_cast<size_type>(__last - __first)), 1784c3eb207Smrg _M_ptr(std::to_address(__first)) 1794c3eb207Smrg { 1804c3eb207Smrg if constexpr (_Extent != dynamic_extent) 1814c3eb207Smrg { 1824c3eb207Smrg __glibcxx_assert((__last - __first) == _Extent); 1834c3eb207Smrg } 184*4ac76180Smrg __glibcxx_requires_valid_range(__first, __last); 1854c3eb207Smrg } 1864c3eb207Smrg 1874c3eb207Smrg template<size_t _ArrayExtent> 1884c3eb207Smrg requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) 1894c3eb207Smrg constexpr 1904c3eb207Smrg span(type_identity_t<element_type> (&__arr)[_ArrayExtent]) noexcept 1914c3eb207Smrg : span(static_cast<pointer>(__arr), _ArrayExtent) 1924c3eb207Smrg { } 1934c3eb207Smrg 1944c3eb207Smrg template<typename _Tp, size_t _ArrayExtent> 1954c3eb207Smrg requires __is_compatible_array<_Tp, _ArrayExtent>::value 1964c3eb207Smrg constexpr 1974c3eb207Smrg span(array<_Tp, _ArrayExtent>& __arr) noexcept 1984c3eb207Smrg : span(static_cast<pointer>(__arr.data()), _ArrayExtent) 1994c3eb207Smrg { } 2004c3eb207Smrg 2014c3eb207Smrg template<typename _Tp, size_t _ArrayExtent> 2024c3eb207Smrg requires __is_compatible_array<const _Tp, _ArrayExtent>::value 2034c3eb207Smrg constexpr 2044c3eb207Smrg span(const array<_Tp, _ArrayExtent>& __arr) noexcept 2054c3eb207Smrg : span(static_cast<pointer>(__arr.data()), _ArrayExtent) 2064c3eb207Smrg { } 2074c3eb207Smrg 2084c3eb207Smrg template<typename _Range> 2094c3eb207Smrg requires (!__detail::__is_std_span<remove_cvref_t<_Range>>::value) 2104c3eb207Smrg && (!__detail::__is_std_array<remove_cvref_t<_Range>>::value) 2114c3eb207Smrg && (!is_array_v<remove_cvref_t<_Range>>) 2124c3eb207Smrg && ranges::contiguous_range<_Range> && ranges::sized_range<_Range> 2134c3eb207Smrg && (ranges::borrowed_range<_Range> || is_const_v<element_type>) 2144c3eb207Smrg && __is_compatible_ref<ranges::range_reference_t<_Range>>::value 2154c3eb207Smrg constexpr explicit(extent != dynamic_extent) 2164c3eb207Smrg span(_Range&& __range) 2174c3eb207Smrg noexcept(noexcept(ranges::data(__range)) 2184c3eb207Smrg && noexcept(ranges::size(__range))) 2194c3eb207Smrg : span(ranges::data(__range), ranges::size(__range)) 2204c3eb207Smrg { 2214c3eb207Smrg if constexpr (extent != dynamic_extent) 2224c3eb207Smrg { 2234c3eb207Smrg __glibcxx_assert(ranges::size(__range) == extent); 2244c3eb207Smrg } 2254c3eb207Smrg } 2264c3eb207Smrg 2274c3eb207Smrg constexpr 2284c3eb207Smrg span(const span&) noexcept = default; 2294c3eb207Smrg 2304c3eb207Smrg template<typename _OType, size_t _OExtent> 2314c3eb207Smrg requires (_Extent == dynamic_extent || _OExtent == dynamic_extent 2324c3eb207Smrg || _Extent == _OExtent) 2334c3eb207Smrg && (__is_array_convertible<_Type, _OType>::value) 2344c3eb207Smrg constexpr 2354c3eb207Smrg explicit(extent != dynamic_extent && _OExtent == dynamic_extent) 2364c3eb207Smrg span(const span<_OType, _OExtent>& __s) noexcept 2374c3eb207Smrg : _M_extent(__s.size()), _M_ptr(__s.data()) 2384c3eb207Smrg { 2394c3eb207Smrg if constexpr (extent != dynamic_extent) 2404c3eb207Smrg { 2414c3eb207Smrg __glibcxx_assert(__s.size() == extent); 2424c3eb207Smrg } 2434c3eb207Smrg } 2444c3eb207Smrg 2454c3eb207Smrg ~span() noexcept = default; 2464c3eb207Smrg 2474c3eb207Smrg constexpr span& 2484c3eb207Smrg operator=(const span&) noexcept = default; 2494c3eb207Smrg 2504c3eb207Smrg // observers 2514c3eb207Smrg 2524c3eb207Smrg constexpr size_type 2534c3eb207Smrg size() const noexcept 2544c3eb207Smrg { return this->_M_extent._M_extent(); } 2554c3eb207Smrg 2564c3eb207Smrg constexpr size_type 2574c3eb207Smrg size_bytes() const noexcept 2584c3eb207Smrg { return this->_M_extent._M_extent() * sizeof(element_type); } 2594c3eb207Smrg 2604c3eb207Smrg [[nodiscard]] constexpr bool 2614c3eb207Smrg empty() const noexcept 2624c3eb207Smrg { return size() == 0; } 2634c3eb207Smrg 2644c3eb207Smrg // element access 2654c3eb207Smrg 2664c3eb207Smrg constexpr reference 2674c3eb207Smrg front() const noexcept 2684c3eb207Smrg { 2694c3eb207Smrg __glibcxx_assert(!empty()); 2704c3eb207Smrg return *this->_M_ptr; 2714c3eb207Smrg } 2724c3eb207Smrg 2734c3eb207Smrg constexpr reference 2744c3eb207Smrg back() const noexcept 2754c3eb207Smrg { 2764c3eb207Smrg __glibcxx_assert(!empty()); 2774c3eb207Smrg return *(this->_M_ptr + (size() - 1)); 2784c3eb207Smrg } 2794c3eb207Smrg 2804c3eb207Smrg constexpr reference 2814c3eb207Smrg operator[](size_type __idx) const noexcept 2824c3eb207Smrg { 2834c3eb207Smrg __glibcxx_assert(__idx < size()); 2844c3eb207Smrg return *(this->_M_ptr + __idx); 2854c3eb207Smrg } 2864c3eb207Smrg 2874c3eb207Smrg constexpr pointer 2884c3eb207Smrg data() const noexcept 2894c3eb207Smrg { return this->_M_ptr; } 2904c3eb207Smrg 2914c3eb207Smrg // iterator support 2924c3eb207Smrg 2934c3eb207Smrg constexpr iterator 2944c3eb207Smrg begin() const noexcept 2954c3eb207Smrg { return iterator(this->_M_ptr); } 2964c3eb207Smrg 2974c3eb207Smrg constexpr iterator 2984c3eb207Smrg end() const noexcept 2994c3eb207Smrg { return iterator(this->_M_ptr + this->size()); } 3004c3eb207Smrg 3014c3eb207Smrg constexpr reverse_iterator 3024c3eb207Smrg rbegin() const noexcept 3034c3eb207Smrg { return reverse_iterator(this->end()); } 3044c3eb207Smrg 3054c3eb207Smrg constexpr reverse_iterator 3064c3eb207Smrg rend() const noexcept 3074c3eb207Smrg { return reverse_iterator(this->begin()); } 3084c3eb207Smrg 3094c3eb207Smrg // subviews 3104c3eb207Smrg 3114c3eb207Smrg template<size_t _Count> 3124c3eb207Smrg constexpr span<element_type, _Count> 3134c3eb207Smrg first() const noexcept 3144c3eb207Smrg { 3154c3eb207Smrg if constexpr (_Extent == dynamic_extent) 3164c3eb207Smrg __glibcxx_assert(_Count <= size()); 3174c3eb207Smrg else 3184c3eb207Smrg static_assert(_Count <= extent); 3194c3eb207Smrg using _Sp = span<element_type, _Count>; 3204c3eb207Smrg return _Sp{ this->data(), _Count }; 3214c3eb207Smrg } 3224c3eb207Smrg 3234c3eb207Smrg constexpr span<element_type, dynamic_extent> 3244c3eb207Smrg first(size_type __count) const noexcept 3254c3eb207Smrg { 3264c3eb207Smrg __glibcxx_assert(__count <= size()); 3274c3eb207Smrg return { this->data(), __count }; 3284c3eb207Smrg } 3294c3eb207Smrg 3304c3eb207Smrg template<size_t _Count> 3314c3eb207Smrg constexpr span<element_type, _Count> 3324c3eb207Smrg last() const noexcept 3334c3eb207Smrg { 3344c3eb207Smrg if constexpr (_Extent == dynamic_extent) 3354c3eb207Smrg __glibcxx_assert(_Count <= size()); 3364c3eb207Smrg else 3374c3eb207Smrg static_assert(_Count <= extent); 3384c3eb207Smrg using _Sp = span<element_type, _Count>; 3394c3eb207Smrg return _Sp{ this->data() + (this->size() - _Count), _Count }; 3404c3eb207Smrg } 3414c3eb207Smrg 3424c3eb207Smrg constexpr span<element_type, dynamic_extent> 3434c3eb207Smrg last(size_type __count) const noexcept 3444c3eb207Smrg { 3454c3eb207Smrg __glibcxx_assert(__count <= size()); 3464c3eb207Smrg return { this->data() + (this->size() - __count), __count }; 3474c3eb207Smrg } 3484c3eb207Smrg 3494c3eb207Smrg template<size_t _Offset, size_t _Count = dynamic_extent> 3504c3eb207Smrg constexpr auto 3514c3eb207Smrg subspan() const noexcept 3524c3eb207Smrg -> span<element_type, _S_subspan_extent<_Offset, _Count>()> 3534c3eb207Smrg { 3544c3eb207Smrg if constexpr (_Extent == dynamic_extent) 3554c3eb207Smrg { 3564c3eb207Smrg __glibcxx_assert(_Offset <= size()); 3574c3eb207Smrg } 3584c3eb207Smrg else 3594c3eb207Smrg static_assert(_Offset <= extent); 3604c3eb207Smrg 3614c3eb207Smrg using _Sp = span<element_type, _S_subspan_extent<_Offset, _Count>()>; 3624c3eb207Smrg 3634c3eb207Smrg if constexpr (_Count == dynamic_extent) 3644c3eb207Smrg return _Sp{ this->data() + _Offset, this->size() - _Offset }; 3654c3eb207Smrg else 3664c3eb207Smrg { 3674c3eb207Smrg if constexpr (_Extent == dynamic_extent) 3684c3eb207Smrg { 3694c3eb207Smrg __glibcxx_assert(_Count <= size()); 3704c3eb207Smrg __glibcxx_assert(_Count <= (size() - _Offset)); 3714c3eb207Smrg } 3724c3eb207Smrg else 3734c3eb207Smrg { 3744c3eb207Smrg static_assert(_Count <= extent); 3754c3eb207Smrg static_assert(_Count <= (extent - _Offset)); 3764c3eb207Smrg } 3774c3eb207Smrg return _Sp{ this->data() + _Offset, _Count }; 3784c3eb207Smrg } 3794c3eb207Smrg } 3804c3eb207Smrg 3814c3eb207Smrg constexpr span<element_type, dynamic_extent> 3824c3eb207Smrg subspan(size_type __offset, size_type __count = dynamic_extent) const 3834c3eb207Smrg noexcept 3844c3eb207Smrg { 3854c3eb207Smrg __glibcxx_assert(__offset <= size()); 3864c3eb207Smrg if (__count == dynamic_extent) 3874c3eb207Smrg __count = this->size() - __offset; 3884c3eb207Smrg else 3894c3eb207Smrg { 3904c3eb207Smrg __glibcxx_assert(__count <= size()); 3914c3eb207Smrg __glibcxx_assert(__offset + __count <= size()); 3924c3eb207Smrg } 3934c3eb207Smrg return {this->data() + __offset, __count}; 3944c3eb207Smrg } 3954c3eb207Smrg 3964c3eb207Smrg private: 3974c3eb207Smrg [[no_unique_address]] __detail::__extent_storage<extent> _M_extent; 3984c3eb207Smrg pointer _M_ptr; 3994c3eb207Smrg }; 4004c3eb207Smrg 4014c3eb207Smrg // deduction guides 4024c3eb207Smrg 4034c3eb207Smrg template<typename _Type, size_t _ArrayExtent> 4044c3eb207Smrg span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>; 4054c3eb207Smrg 4064c3eb207Smrg template<typename _Type, size_t _ArrayExtent> 4074c3eb207Smrg span(array<_Type, _ArrayExtent>&) -> span<_Type, _ArrayExtent>; 4084c3eb207Smrg 4094c3eb207Smrg template<typename _Type, size_t _ArrayExtent> 4104c3eb207Smrg span(const array<_Type, _ArrayExtent>&) 4114c3eb207Smrg -> span<const _Type, _ArrayExtent>; 4124c3eb207Smrg 4134c3eb207Smrg template<contiguous_iterator _Iter, typename _End> 4144c3eb207Smrg span(_Iter, _End) 4154c3eb207Smrg -> span<remove_reference_t<iter_reference_t<_Iter>>>; 4164c3eb207Smrg 4174c3eb207Smrg template<ranges::contiguous_range _Range> 4184c3eb207Smrg span(_Range &&) 4194c3eb207Smrg -> span<remove_reference_t<ranges::range_reference_t<_Range&>>>; 4204c3eb207Smrg 4214c3eb207Smrg template<typename _Type, size_t _Extent> 4224c3eb207Smrg inline 4234c3eb207Smrg span<const byte, _Extent == dynamic_extent 4244c3eb207Smrg ? dynamic_extent : _Extent * sizeof(_Type)> 4254c3eb207Smrg as_bytes(span<_Type, _Extent> __sp) noexcept 4264c3eb207Smrg { 4274c3eb207Smrg auto data = reinterpret_cast<const byte*>(__sp.data()); 4284c3eb207Smrg auto size = __sp.size_bytes(); 4294c3eb207Smrg constexpr auto extent = _Extent == dynamic_extent 4304c3eb207Smrg ? dynamic_extent : _Extent * sizeof(_Type); 4314c3eb207Smrg return span<const byte, extent>{data, size}; 4324c3eb207Smrg } 4334c3eb207Smrg 4344c3eb207Smrg template<typename _Type, size_t _Extent> 4354c3eb207Smrg requires (!is_const_v<_Type>) 4364c3eb207Smrg inline 4374c3eb207Smrg span<byte, _Extent == dynamic_extent 4384c3eb207Smrg ? dynamic_extent : _Extent * sizeof(_Type)> 4394c3eb207Smrg as_writable_bytes(span<_Type, _Extent> __sp) noexcept 4404c3eb207Smrg { 4414c3eb207Smrg auto data = reinterpret_cast<byte*>(__sp.data()); 4424c3eb207Smrg auto size = __sp.size_bytes(); 4434c3eb207Smrg constexpr auto extent = _Extent == dynamic_extent 4444c3eb207Smrg ? dynamic_extent : _Extent * sizeof(_Type); 4454c3eb207Smrg return span<byte, extent>{data, size}; 4464c3eb207Smrg } 4474c3eb207Smrg 4484c3eb207Smrg namespace ranges 4494c3eb207Smrg { 4504c3eb207Smrg // Opt-in to borrowed_range concept 4514c3eb207Smrg template<typename _ElementType, size_t _Extent> 4524c3eb207Smrg inline constexpr bool 4534c3eb207Smrg enable_borrowed_range<span<_ElementType, _Extent>> = true; 4544c3eb207Smrg 4554c3eb207Smrg // Opt-in to view concept 4564c3eb207Smrg template<typename _ElementType, size_t _Extent> 4574c3eb207Smrg inline constexpr bool 4584c3eb207Smrg enable_view<span<_ElementType, _Extent>> = true; 4594c3eb207Smrg } 4604c3eb207Smrg_GLIBCXX_END_NAMESPACE_VERSION 4614c3eb207Smrg} // namespace std 4624c3eb207Smrg#endif // concepts 4634c3eb207Smrg#endif // C++20 4644c3eb207Smrg#endif // _GLIBCXX_SPAN 465