Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/c++/15/span
1 // Components for manipulating non-owning sequences of objects -*- C++ -*- 2 3 // Copyright (C) 2019-2025 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 #ifdef _GLIBCXX_SYSHDR 38 #pragma GCC system_header 39 #endif 40 41 #define __glibcxx_want_span 42 #define __glibcxx_want_span_initializer_list 43 #include <bits/version.h> 44 45 #ifdef __cpp_lib_span // C++ >= 20 && concepts 46 #include <array> 47 #include <cstddef> 48 #include <bits/stl_iterator.h> 49 #include <bits/ranges_base.h> 50 #ifdef __cpp_lib_span_initializer_list 51 # include <initializer_list> 52 #endif 53 namespace std _GLIBCXX_VISIBILITY(default) 54 { 55 _GLIBCXX_BEGIN_NAMESPACE_VERSION 56 57 inline constexpr size_t dynamic_extent = static_cast<size_t>(-1); 58 59 template<typename _Type, size_t _Extent> 60 class span; 61 62 namespace __detail 63 { 64 template<typename _Tp> 65 inline constexpr bool __is_span = false; 66 67 template<typename _Tp, size_t _Num> 68 inline constexpr bool __is_span<span<_Tp, _Num>> = true; 69 70 template<typename _Tp> 71 inline constexpr bool __is_std_array = false; 72 73 template<typename _Tp, size_t _Num> 74 inline constexpr bool __is_std_array<std::array<_Tp, _Num>> = true; 75 76 template<size_t _Extent> 77 class __extent_storage 78 { 79 public: 80 // Used for runtime sizes that must satisfy the precondition. 81 constexpr 82 __extent_storage([[maybe_unused]] size_t __n) noexcept 83 { __glibcxx_assert(__n == _Extent); } 84 85 // Used for constant sizes that are already known to be correct. 86 consteval 87 __extent_storage(integral_constant<size_t, _Extent>) noexcept 88 { } 89 90 // "I've made a huge mistake" - George Oscar Bluth II 91 template<size_t _Gob> 92 __extent_storage(integral_constant<size_t, _Gob>) = delete; 93 94 [[__gnu__::__always_inline__]] 95 static constexpr size_t 96 _M_extent() noexcept 97 { return _Extent; } 98 }; 99 100 template<> 101 class __extent_storage<dynamic_extent> 102 { 103 public: 104 [[__gnu__::__always_inline__]] 105 constexpr 106 __extent_storage(size_t __extent) noexcept 107 : _M_extent_value(__extent) 108 { } 109 110 [[__gnu__::__always_inline__]] 111 constexpr size_t 112 _M_extent() const noexcept 113 { return this->_M_extent_value; } 114 115 private: 116 size_t _M_extent_value; 117 }; 118 119 template<typename _Type> struct __span_ptr { _Type* const _M_ptr; }; 120 121 } // namespace __detail 122 123 template<typename _Type, size_t _Extent = dynamic_extent> 124 class span 125 { 126 template<size_t _Offset, size_t _Count> 127 static constexpr size_t 128 _S_subspan_extent() 129 { 130 if constexpr (_Count != dynamic_extent) 131 return _Count; 132 else if constexpr (extent != dynamic_extent) 133 return _Extent - _Offset; 134 else 135 return dynamic_extent; 136 } 137 138 // _GLIBCXX_RESOLVE_LIB_DEFECTS 139 // 3255. span's array constructor is too strict 140 template<typename _Tp, size_t _ArrayExtent> 141 requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) 142 using __is_compatible_array = __is_array_convertible<_Type, _Tp>; 143 144 template<typename _Ref> 145 using __is_compatible_ref 146 = __is_array_convertible<_Type, remove_reference_t<_Ref>>; 147 148 // Nested type so that _Type is not an associated class of iterator. 149 struct __iter_tag; 150 151 template<size_t _Nm> 152 static inline constexpr integral_constant<size_t, _Nm> __v{}; 153 154 public: 155 // member types 156 using element_type = _Type; 157 using value_type = remove_cv_t<_Type>; 158 using size_type = size_t; 159 using difference_type = ptrdiff_t; 160 using pointer = _Type*; 161 using const_pointer = const _Type*; 162 using reference = element_type&; 163 using const_reference = const element_type&; 164 using iterator = __gnu_cxx::__normal_iterator<pointer, __iter_tag>; 165 using reverse_iterator = std::reverse_iterator<iterator>; 166 #if __cplusplus > 202002L 167 using const_iterator = std::const_iterator<iterator>; 168 using const_reverse_iterator = std::const_iterator<reverse_iterator>; 169 #endif 170 171 // member constants 172 static constexpr size_t extent = _Extent; 173 174 // constructors, copy and assignment 175 176 constexpr 177 span() noexcept 178 requires (_Extent == dynamic_extent || _Extent == 0) 179 : _M_ptr(nullptr), _M_extent(__v<0>) 180 { } 181 182 template<contiguous_iterator _It> 183 requires __is_compatible_ref<iter_reference_t<_It>>::value 184 constexpr explicit(extent != dynamic_extent) 185 span(_It __first, size_type __count) 186 noexcept 187 : _M_ptr(std::to_address(__first)), _M_extent(__count) 188 { __glibcxx_requires_valid_range(__first, __first + __count); } 189 190 template<contiguous_iterator _It, sized_sentinel_for<_It> _End> 191 requires __is_compatible_ref<iter_reference_t<_It>>::value 192 && (!is_convertible_v<_End, size_type>) 193 constexpr explicit(extent != dynamic_extent) 194 span(_It __first, _End __last) 195 noexcept(noexcept(__last - __first)) 196 : _M_ptr(std::to_address(__first)), 197 _M_extent(static_cast<size_type>(__last - __first)) 198 { __glibcxx_requires_valid_range(__first, __last); } 199 200 template<size_t _ArrayExtent> 201 requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) 202 constexpr 203 span(type_identity_t<element_type> (&__arr)[_ArrayExtent]) noexcept 204 : _M_ptr(__arr), _M_extent(__v<_ArrayExtent>) 205 { } 206 207 template<typename _Tp, size_t _ArrayExtent> 208 requires __is_compatible_array<_Tp, _ArrayExtent>::value 209 constexpr 210 span(array<_Tp, _ArrayExtent>& __arr) noexcept 211 : _M_ptr(__arr.data()), _M_extent(__v<_ArrayExtent>) 212 { } 213 214 template<typename _Tp, size_t _ArrayExtent> 215 requires __is_compatible_array<const _Tp, _ArrayExtent>::value 216 constexpr 217 span(const array<_Tp, _ArrayExtent>& __arr) noexcept 218 : _M_ptr(__arr.data()), _M_extent(__v<_ArrayExtent>) 219 { } 220 221 template<typename _Range> 222 requires (!__detail::__is_span<remove_cvref_t<_Range>>) 223 && (!__detail::__is_std_array<remove_cvref_t<_Range>>) 224 && (!is_array_v<remove_cvref_t<_Range>>) 225 && ranges::contiguous_range<_Range> && ranges::sized_range<_Range> 226 && (ranges::borrowed_range<_Range> || is_const_v<element_type>) 227 && __is_compatible_ref<ranges::range_reference_t<_Range>>::value 228 constexpr explicit(extent != dynamic_extent) 229 span(_Range&& __range) 230 noexcept(noexcept(ranges::data(__range)) 231 && noexcept(ranges::size(__range))) 232 : _M_ptr(ranges::data(__range)), _M_extent(ranges::size(__range)) 233 { } 234 235 #if __cpp_lib_span_initializer_list >= 202311L // >= C++26 236 #pragma GCC diagnostic push 237 #pragma GCC diagnostic ignored "-Winit-list-lifetime" 238 constexpr 239 explicit(extent != dynamic_extent) 240 span(initializer_list<value_type> __il) 241 requires (is_const_v<_Type>) 242 : _M_ptr(__il.begin()), _M_extent(__il.size()) 243 { } 244 #pragma GCC diagnostic pop 245 #endif 246 247 constexpr 248 span(const span&) noexcept = default; 249 250 template<typename _OType, size_t _OExtent> 251 requires (_Extent == dynamic_extent || _OExtent == dynamic_extent 252 || _Extent == _OExtent) 253 && (__is_array_convertible<_Type, _OType>::value) 254 constexpr 255 explicit(extent != dynamic_extent && _OExtent == dynamic_extent) 256 span(const span<_OType, _OExtent>& __s) noexcept 257 : _M_ptr(__s.data()), _M_extent(__s.size()) 258 { } 259 260 constexpr span& 261 operator=(const span&) noexcept = default; 262 263 // observers 264 265 [[nodiscard]] 266 constexpr size_type 267 size() const noexcept 268 { return this->_M_extent._M_extent(); } 269 270 [[nodiscard]] 271 constexpr size_type 272 size_bytes() const noexcept 273 { return this->_M_extent._M_extent() * sizeof(element_type); } 274 275 [[nodiscard]] 276 constexpr bool 277 empty() const noexcept 278 { return size() == 0; } 279 280 // element access 281 282 [[nodiscard]] 283 constexpr reference 284 front() const noexcept 285 { 286 __glibcxx_assert(!empty()); 287 return *this->_M_ptr; 288 } 289 290 [[nodiscard]] 291 constexpr reference 292 back() const noexcept 293 { 294 __glibcxx_assert(!empty()); 295 return *(this->_M_ptr + (size() - 1)); 296 } 297 298 [[nodiscard]] 299 constexpr reference 300 operator[](size_type __idx) const noexcept 301 { 302 __glibcxx_assert(__idx < size()); 303 return *(this->_M_ptr + __idx); 304 } 305 306 #if __cpp_lib_span >= 202311L // >= C++26 307 [[nodiscard]] 308 constexpr reference 309 at(size_type __idx) const 310 { 311 if (__idx >= size()) 312 __throw_out_of_range_fmt(__N("span::at(%zu) out-of-range for span " 313 "of size %zu"), __idx, this->size()); 314 return *(this->_M_ptr + __idx); 315 } 316 #endif 317 318 [[nodiscard]] 319 constexpr pointer 320 data() const noexcept 321 { return this->_M_ptr; } 322 323 // iterator support 324 325 [[nodiscard]] 326 constexpr iterator 327 begin() const noexcept 328 { return iterator(this->_M_ptr); } 329 330 [[nodiscard]] 331 constexpr iterator 332 end() const noexcept 333 { return iterator(this->_M_ptr + this->size()); } 334 335 [[nodiscard]] 336 constexpr reverse_iterator 337 rbegin() const noexcept 338 { return reverse_iterator(this->end()); } 339 340 [[nodiscard]] 341 constexpr reverse_iterator 342 rend() const noexcept 343 { return reverse_iterator(this->begin()); } 344 345 #if __cplusplus > 202002L 346 [[nodiscard]] 347 constexpr const_iterator 348 cbegin() const noexcept 349 { return begin(); } 350 351 [[nodiscard]] 352 constexpr const_iterator 353 cend() const noexcept 354 { return end(); } 355 356 [[nodiscard]] 357 constexpr const_reverse_iterator 358 crbegin() const noexcept 359 { return rbegin(); } 360 361 [[nodiscard]] 362 constexpr const_reverse_iterator 363 crend() const noexcept 364 { return rend(); } 365 #endif 366 367 // subviews 368 369 template<size_t _Count> 370 [[nodiscard]] 371 constexpr span<element_type, _Count> 372 first() const noexcept 373 { 374 if constexpr (_Extent == dynamic_extent) 375 __glibcxx_assert(_Count <= size()); 376 else 377 static_assert(_Count <= extent); 378 using _Sp = span<element_type, _Count>; 379 return _Sp(_SizedPtr{this->data()}); 380 } 381 382 [[nodiscard]] 383 constexpr span<element_type, dynamic_extent> 384 first(size_type __count) const noexcept 385 { 386 __glibcxx_assert(__count <= size()); 387 return span<element_type>(this->data(), __count); 388 } 389 390 template<size_t _Count> 391 [[nodiscard]] 392 constexpr span<element_type, _Count> 393 last() const noexcept 394 { 395 if constexpr (_Extent == dynamic_extent) 396 __glibcxx_assert(_Count <= size()); 397 else 398 static_assert(_Count <= extent); 399 using _Sp = span<element_type, _Count>; 400 return _Sp(_SizedPtr{this->data() + (this->size() - _Count)}); 401 } 402 403 [[nodiscard]] 404 constexpr span<element_type, dynamic_extent> 405 last(size_type __count) const noexcept 406 { 407 __glibcxx_assert(__count <= size()); 408 return span<element_type>(this->data() + (this->size() - __count), 409 __count); 410 } 411 412 template<size_t _Offset, size_t _Count = dynamic_extent> 413 [[nodiscard]] 414 constexpr auto 415 subspan() const noexcept 416 -> span<element_type, _S_subspan_extent<_Offset, _Count>()> 417 { 418 if constexpr (_Extent == dynamic_extent) 419 { 420 __glibcxx_assert(_Offset <= size()); 421 } 422 else 423 static_assert(_Offset <= extent); 424 425 using _Sp = span<element_type, _S_subspan_extent<_Offset, _Count>()>; 426 427 if constexpr (_Count == dynamic_extent) 428 return _Sp(this->data() + _Offset, this->size() - _Offset); 429 else 430 { 431 if constexpr (_Extent == dynamic_extent) 432 { 433 __glibcxx_assert(_Count <= size()); 434 __glibcxx_assert(_Count <= (size() - _Offset)); 435 } 436 else 437 { 438 static_assert(_Count <= extent); 439 static_assert(_Count <= (extent - _Offset)); 440 } 441 return _Sp(_SizedPtr{this->data() + _Offset}); 442 } 443 } 444 445 [[nodiscard]] 446 constexpr span<element_type, dynamic_extent> 447 subspan(size_type __offset, size_type __count = dynamic_extent) const 448 noexcept 449 { 450 __glibcxx_assert(__offset <= size()); 451 if (__count == dynamic_extent) 452 __count = this->size() - __offset; 453 else 454 { 455 __glibcxx_assert(__count <= size()); 456 __glibcxx_assert(__offset + __count <= size()); 457 } 458 return span<element_type>(this->data() + __offset, __count); 459 } 460 461 private: 462 template<typename, size_t> friend class span; 463 464 // Tag type for pointer that has known extent. 465 using _SizedPtr = __detail::__span_ptr<_Type>; 466 467 // Private constructor with an implied extent. 468 [[__gnu__::__always_inline__]] 469 constexpr explicit 470 span(_SizedPtr __ptr) noexcept 471 requires (extent != dynamic_extent) 472 : _M_ptr(__ptr._M_ptr), _M_extent(__v<extent>) 473 { } 474 475 pointer _M_ptr; 476 [[no_unique_address]] __detail::__extent_storage<extent> _M_extent; 477 }; 478 479 // deduction guides 480 481 template<typename _Type, size_t _ArrayExtent> 482 span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>; 483 484 template<typename _Type, size_t _ArrayExtent> 485 span(array<_Type, _ArrayExtent>&) -> span<_Type, _ArrayExtent>; 486 487 template<typename _Type, size_t _ArrayExtent> 488 span(const array<_Type, _ArrayExtent>&) 489 -> span<const _Type, _ArrayExtent>; 490 491 template<contiguous_iterator _Iter, typename _End> 492 span(_Iter, _End) 493 -> span<remove_reference_t<iter_reference_t<_Iter>>>; 494 495 template<ranges::contiguous_range _Range> 496 span(_Range &&) 497 -> span<remove_reference_t<ranges::range_reference_t<_Range&>>>; 498 499 template<typename _Type, size_t _Extent> 500 [[nodiscard]] 501 inline 502 span<const byte, _Extent == dynamic_extent 503 ? dynamic_extent : _Extent * sizeof(_Type)> 504 as_bytes(span<_Type, _Extent> __sp) noexcept 505 { 506 auto data = reinterpret_cast<const byte*>(__sp.data()); 507 auto size = __sp.size_bytes(); 508 constexpr auto extent = _Extent == dynamic_extent 509 ? dynamic_extent : _Extent * sizeof(_Type); 510 return span<const byte, extent>{data, size}; 511 } 512 513 template<typename _Type, size_t _Extent> 514 requires (!is_const_v<_Type>) 515 inline 516 span<byte, _Extent == dynamic_extent 517 ? dynamic_extent : _Extent * sizeof(_Type)> 518 as_writable_bytes [[nodiscard]] (span<_Type, _Extent> __sp) noexcept 519 { 520 auto data = reinterpret_cast<byte*>(__sp.data()); 521 auto size = __sp.size_bytes(); 522 constexpr auto extent = _Extent == dynamic_extent 523 ? dynamic_extent : _Extent * sizeof(_Type); 524 return span<byte, extent>{data, size}; 525 } 526 527 namespace ranges 528 { 529 // Opt-in to borrowed_range concept 530 template<typename _ElementType, size_t _Extent> 531 inline constexpr bool 532 enable_borrowed_range<span<_ElementType, _Extent>> = true; 533 534 // Opt-in to view concept 535 template<typename _ElementType, size_t _Extent> 536 inline constexpr bool 537 enable_view<span<_ElementType, _Extent>> = true; 538 } 539 _GLIBCXX_END_NAMESPACE_VERSION 540 } // namespace std 541 #endif // __cpp_lib_span 542 #endif // _GLIBCXX_SPAN