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