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