[1166] | 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
|
---|