]>
Commit | Line | Data |
---|---|---|
95e9a761 JM |
1 | // Components for manipulating non-owning sequences of objects -*- C++ -*- |
2 | ||
99dee823 | 3 | // Copyright (C) 2019-2021 Free Software Foundation, Inc. |
95e9a761 JM |
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 | ||
95e9a761 | 41 | #include <array> |
0f7cd5e5 | 42 | #include <cstddef> |
95e9a761 | 43 | #include <bits/stl_iterator.h> |
160061ac | 44 | #include <bits/ranges_base.h> |
95e9a761 | 45 | |
a7922ddf | 46 | #if __cpp_lib_concepts |
95e9a761 JM |
47 | namespace std _GLIBCXX_VISIBILITY(default) |
48 | { | |
49 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
50 | ||
9b8e2dea | 51 | #define __cpp_lib_span 202002L |
95e9a761 JM |
52 | |
53 | inline constexpr size_t dynamic_extent = static_cast<size_t>(-1); | |
54 | ||
27dada7d JW |
55 | template<typename _Type, size_t _Extent> |
56 | class span; | |
57 | ||
95e9a761 JM |
58 | namespace __detail |
59 | { | |
27dada7d JW |
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 { }; | |
95e9a761 JM |
65 | |
66 | template<typename _Tp> | |
27dada7d | 67 | struct __is_std_array : false_type { }; |
95e9a761 JM |
68 | |
69 | template<typename _Tp, size_t _Num> | |
6db08247 | 70 | struct __is_std_array<std::array<_Tp, _Num>> : true_type { }; |
95e9a761 JM |
71 | |
72 | template<size_t _Extent> | |
73 | class __extent_storage | |
74 | { | |
75 | public: | |
95e9a761 JM |
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<> | |
b5c433ce | 86 | class __extent_storage<dynamic_extent> |
95e9a761 JM |
87 | { |
88 | public: | |
95e9a761 JM |
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 | }; | |
95e9a761 JM |
101 | } // namespace __detail |
102 | ||
103 | template<typename _Type, size_t _Extent = dynamic_extent> | |
b5c433ce | 104 | class span |
95e9a761 | 105 | { |
b5c433ce JW |
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 | ||
582c57a1 JW |
118 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
119 | // 3255. span's array constructor is too strict | |
a7922ddf | 120 | template<typename _Tp, size_t _ArrayExtent> |
d6c9e372 JW |
121 | requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) |
122 | using __is_compatible_array = __is_array_convertible<_Type, _Tp>; | |
a7922ddf | 123 | |
d6c9e372 JW |
124 | template<typename _Ref> |
125 | using __is_compatible_ref | |
126 | = __is_array_convertible<_Type, remove_reference_t<_Ref>>; | |
582c57a1 | 127 | |
95e9a761 JM |
128 | public: |
129 | // member types | |
95e9a761 | 130 | using element_type = _Type; |
f09f3242 | 131 | using value_type = remove_cv_t<_Type>; |
a7922ddf | 132 | using size_type = size_t; |
f09f3242 | 133 | using difference_type = ptrdiff_t; |
95e9a761 JM |
134 | using pointer = _Type*; |
135 | using const_pointer = const _Type*; | |
f09f3242 JW |
136 | using reference = element_type&; |
137 | using const_reference = const element_type&; | |
138 | using iterator = __gnu_cxx::__normal_iterator<pointer, span>; | |
95e9a761 | 139 | using reverse_iterator = std::reverse_iterator<iterator>; |
95e9a761 JM |
140 | |
141 | // member constants | |
f09f3242 | 142 | static constexpr size_t extent = _Extent; |
95e9a761 | 143 | |
f09f3242 | 144 | // constructors, copy and assignment |
95e9a761 | 145 | |
a7922ddf JTM |
146 | constexpr |
147 | span() noexcept | |
148 | requires ((_Extent + 1u) <= 1u) | |
0f7cd5e5 | 149 | : _M_ptr(nullptr), _M_extent(0) |
a7922ddf | 150 | { } |
95e9a761 | 151 | |
f09f3242 | 152 | template<contiguous_iterator _It> |
d6c9e372 | 153 | requires __is_compatible_ref<iter_reference_t<_It>>::value |
9b8e2dea | 154 | constexpr explicit(extent != dynamic_extent) |
f09f3242 JW |
155 | span(_It __first, size_type __count) |
156 | noexcept | |
0f7cd5e5 | 157 | : _M_ptr(std::to_address(__first)), _M_extent(__count) |
9b8e2dea JW |
158 | { |
159 | if constexpr (_Extent != dynamic_extent) | |
160 | { | |
161 | __glibcxx_assert(__count == _Extent); | |
162 | } | |
163 | } | |
f09f3242 JW |
164 | |
165 | template<contiguous_iterator _It, sized_sentinel_for<_It> _End> | |
d6c9e372 JW |
166 | requires __is_compatible_ref<iter_reference_t<_It>>::value |
167 | && (!is_convertible_v<_End, size_type>) | |
9b8e2dea | 168 | constexpr explicit(extent != dynamic_extent) |
f09f3242 JW |
169 | span(_It __first, _End __last) |
170 | noexcept(noexcept(__last - __first)) | |
0f7cd5e5 JW |
171 | : _M_ptr(std::to_address(__first)), |
172 | _M_extent(static_cast<size_type>(__last - __first)) | |
f09f3242 | 173 | { |
9b8e2dea JW |
174 | if constexpr (_Extent != dynamic_extent) |
175 | { | |
176 | __glibcxx_assert((__last - __first) == _Extent); | |
177 | } | |
f09f3242 | 178 | } |
95e9a761 | 179 | |
66ae31eb JW |
180 | template<size_t _ArrayExtent> |
181 | requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) | |
27dada7d | 182 | constexpr |
66ae31eb | 183 | span(type_identity_t<element_type> (&__arr)[_ArrayExtent]) noexcept |
27dada7d | 184 | : span(static_cast<pointer>(__arr), _ArrayExtent) |
95e9a761 JM |
185 | { } |
186 | ||
a7922ddf | 187 | template<typename _Tp, size_t _ArrayExtent> |
d6c9e372 | 188 | requires __is_compatible_array<_Tp, _ArrayExtent>::value |
95e9a761 | 189 | constexpr |
582c57a1 JW |
190 | span(array<_Tp, _ArrayExtent>& __arr) noexcept |
191 | : span(static_cast<pointer>(__arr.data()), _ArrayExtent) | |
95e9a761 JM |
192 | { } |
193 | ||
a7922ddf | 194 | template<typename _Tp, size_t _ArrayExtent> |
d6c9e372 | 195 | requires __is_compatible_array<const _Tp, _ArrayExtent>::value |
95e9a761 | 196 | constexpr |
582c57a1 JW |
197 | span(const array<_Tp, _ArrayExtent>& __arr) noexcept |
198 | : span(static_cast<pointer>(__arr.data()), _ArrayExtent) | |
95e9a761 JM |
199 | { } |
200 | ||
d6c9e372 | 201 | template<typename _Range> |
9b8e2dea | 202 | requires ranges::contiguous_range<_Range> && ranges::sized_range<_Range> |
15411a64 | 203 | && (ranges::borrowed_range<_Range> || is_const_v<element_type>) |
a7922ddf JTM |
204 | && (!__detail::__is_std_span<remove_cvref_t<_Range>>::value) |
205 | && (!__detail::__is_std_array<remove_cvref_t<_Range>>::value) | |
d6c9e372 JW |
206 | && (!is_array_v<remove_cvref_t<_Range>>) |
207 | && __is_compatible_ref<ranges::range_reference_t<_Range>>::value | |
9b8e2dea | 208 | constexpr explicit(extent != dynamic_extent) |
95e9a761 | 209 | span(_Range&& __range) |
a7922ddf JTM |
210 | noexcept(noexcept(ranges::data(__range)) |
211 | && noexcept(ranges::size(__range))) | |
212 | : span(ranges::data(__range), ranges::size(__range)) | |
9b8e2dea JW |
213 | { |
214 | if constexpr (extent != dynamic_extent) | |
215 | { | |
216 | __glibcxx_assert(ranges::size(__range) == extent); | |
217 | } | |
218 | } | |
95e9a761 | 219 | |
f09f3242 JW |
220 | constexpr |
221 | span(const span&) noexcept = default; | |
27dada7d | 222 | |
a7922ddf | 223 | template<typename _OType, size_t _OExtent> |
9b8e2dea JW |
224 | requires (_Extent == dynamic_extent || _OExtent == dynamic_extent |
225 | || _Extent == _OExtent) | |
a7922ddf | 226 | && (__is_array_convertible<_Type, _OType>::value) |
27dada7d | 227 | constexpr |
9b8e2dea | 228 | explicit(extent != dynamic_extent && _OExtent == dynamic_extent) |
27dada7d JW |
229 | span(const span<_OType, _OExtent>& __s) noexcept |
230 | : _M_extent(__s.size()), _M_ptr(__s.data()) | |
9b8e2dea JW |
231 | { |
232 | if constexpr (extent != dynamic_extent) | |
233 | { | |
234 | __glibcxx_assert(__s.size() == extent); | |
235 | } | |
236 | } | |
27dada7d | 237 | |
f09f3242 | 238 | ~span() noexcept = default; |
95e9a761 JM |
239 | |
240 | constexpr span& | |
241 | operator=(const span&) noexcept = default; | |
242 | ||
b5c433ce JW |
243 | // observers |
244 | ||
a7922ddf | 245 | constexpr size_type |
b5c433ce JW |
246 | size() const noexcept |
247 | { return this->_M_extent._M_extent(); } | |
248 | ||
a7922ddf | 249 | constexpr size_type |
b5c433ce JW |
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 | |
95e9a761 JM |
258 | |
259 | constexpr reference | |
260 | front() const noexcept | |
b5c433ce | 261 | { |
b5c433ce JW |
262 | __glibcxx_assert(!empty()); |
263 | return *this->_M_ptr; | |
264 | } | |
95e9a761 JM |
265 | |
266 | constexpr reference | |
267 | back() const noexcept | |
268 | { | |
b5c433ce JW |
269 | __glibcxx_assert(!empty()); |
270 | return *(this->_M_ptr + (size() - 1)); | |
95e9a761 JM |
271 | } |
272 | ||
273 | constexpr reference | |
a7922ddf | 274 | operator[](size_type __idx) const noexcept |
b5c433ce | 275 | { |
b5c433ce JW |
276 | __glibcxx_assert(__idx < size()); |
277 | return *(this->_M_ptr + __idx); | |
278 | } | |
95e9a761 JM |
279 | |
280 | constexpr pointer | |
281 | data() const noexcept | |
282 | { return this->_M_ptr; } | |
283 | ||
b5c433ce | 284 | // iterator support |
95e9a761 | 285 | |
95e9a761 JM |
286 | constexpr iterator |
287 | begin() const noexcept | |
288 | { return iterator(this->_M_ptr); } | |
289 | ||
95e9a761 JM |
290 | constexpr iterator |
291 | end() const noexcept | |
292 | { return iterator(this->_M_ptr + this->size()); } | |
293 | ||
95e9a761 JM |
294 | constexpr reverse_iterator |
295 | rbegin() const noexcept | |
296 | { return reverse_iterator(this->end()); } | |
297 | ||
95e9a761 JM |
298 | constexpr reverse_iterator |
299 | rend() const noexcept | |
300 | { return reverse_iterator(this->begin()); } | |
301 | ||
b5c433ce JW |
302 | // subviews |
303 | ||
95e9a761 JM |
304 | template<size_t _Count> |
305 | constexpr span<element_type, _Count> | |
b5c433ce | 306 | first() const noexcept |
95e9a761 | 307 | { |
b5c433ce JW |
308 | if constexpr (_Extent == dynamic_extent) |
309 | __glibcxx_assert(_Count <= size()); | |
310 | else | |
311 | static_assert(_Count <= extent); | |
9b8e2dea JW |
312 | using _Sp = span<element_type, _Count>; |
313 | return _Sp{ this->data(), _Count }; | |
95e9a761 JM |
314 | } |
315 | ||
316 | constexpr span<element_type, dynamic_extent> | |
a7922ddf | 317 | first(size_type __count) const noexcept |
95e9a761 | 318 | { |
b5c433ce | 319 | __glibcxx_assert(__count <= size()); |
95e9a761 JM |
320 | return { this->data(), __count }; |
321 | } | |
322 | ||
323 | template<size_t _Count> | |
324 | constexpr span<element_type, _Count> | |
b5c433ce | 325 | last() const noexcept |
95e9a761 | 326 | { |
b5c433ce JW |
327 | if constexpr (_Extent == dynamic_extent) |
328 | __glibcxx_assert(_Count <= size()); | |
329 | else | |
330 | static_assert(_Count <= extent); | |
9b8e2dea JW |
331 | using _Sp = span<element_type, _Count>; |
332 | return _Sp{ this->data() + (this->size() - _Count), _Count }; | |
95e9a761 JM |
333 | } |
334 | ||
335 | constexpr span<element_type, dynamic_extent> | |
a7922ddf | 336 | last(size_type __count) const noexcept |
95e9a761 | 337 | { |
b5c433ce JW |
338 | __glibcxx_assert(__count <= size()); |
339 | return { this->data() + (this->size() - __count), __count }; | |
95e9a761 JM |
340 | } |
341 | ||
342 | template<size_t _Offset, size_t _Count = dynamic_extent> | |
343 | constexpr auto | |
b5c433ce JW |
344 | subspan() const noexcept |
345 | -> span<element_type, _S_subspan_extent<_Offset, _Count>()> | |
95e9a761 | 346 | { |
b5c433ce | 347 | if constexpr (_Extent == dynamic_extent) |
9b8e2dea JW |
348 | { |
349 | __glibcxx_assert(_Offset <= size()); | |
350 | } | |
b5c433ce JW |
351 | else |
352 | static_assert(_Offset <= extent); | |
353 | ||
9b8e2dea JW |
354 | using _Sp = span<element_type, _S_subspan_extent<_Offset, _Count>()>; |
355 | ||
b5c433ce | 356 | if constexpr (_Count == dynamic_extent) |
9b8e2dea | 357 | return _Sp{ this->data() + _Offset, this->size() - _Offset }; |
b5c433ce | 358 | else |
95e9a761 | 359 | { |
b5c433ce JW |
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 | } | |
9b8e2dea | 370 | return _Sp{ this->data() + _Offset, _Count }; |
95e9a761 | 371 | } |
95e9a761 JM |
372 | } |
373 | ||
374 | constexpr span<element_type, dynamic_extent> | |
a7922ddf | 375 | subspan(size_type __offset, size_type __count = dynamic_extent) const |
b5c433ce | 376 | noexcept |
95e9a761 | 377 | { |
b5c433ce JW |
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}; | |
95e9a761 JM |
387 | } |
388 | ||
95e9a761 JM |
389 | private: |
390 | pointer _M_ptr; | |
0f7cd5e5 | 391 | [[no_unique_address]] __detail::__extent_storage<extent> _M_extent; |
95e9a761 JM |
392 | }; |
393 | ||
394 | // deduction guides | |
389cd88c | 395 | |
95e9a761 | 396 | template<typename _Type, size_t _ArrayExtent> |
b5c433ce | 397 | span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>; |
95e9a761 JM |
398 | |
399 | template<typename _Type, size_t _ArrayExtent> | |
b5c433ce | 400 | span(array<_Type, _ArrayExtent>&) -> span<_Type, _ArrayExtent>; |
95e9a761 JM |
401 | |
402 | template<typename _Type, size_t _ArrayExtent> | |
403 | span(const array<_Type, _ArrayExtent>&) | |
b5c433ce | 404 | -> span<const _Type, _ArrayExtent>; |
95e9a761 | 405 | |
f09f3242 JW |
406 | template<contiguous_iterator _Iter, typename _End> |
407 | span(_Iter, _End) | |
389cd88c | 408 | -> span<remove_reference_t<iter_reference_t<_Iter>>>; |
95e9a761 JM |
409 | |
410 | template<typename _Range> | |
411 | span(_Range &&) | |
a7922ddf | 412 | -> span<remove_reference_t<ranges::range_reference_t<_Range&>>>; |
95e9a761 JM |
413 | |
414 | template<typename _Type, size_t _Extent> | |
b5c433ce | 415 | inline |
95e9a761 JM |
416 | span<const byte, _Extent == dynamic_extent |
417 | ? dynamic_extent : _Extent * sizeof(_Type)> | |
b5c433ce | 418 | as_bytes(span<_Type, _Extent> __sp) noexcept |
95e9a761 | 419 | { |
9b8e2dea JW |
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}; | |
95e9a761 JM |
425 | } |
426 | ||
427 | template<typename _Type, size_t _Extent> | |
b5c433ce | 428 | inline |
95e9a761 JM |
429 | span<byte, _Extent == dynamic_extent |
430 | ? dynamic_extent : _Extent * sizeof(_Type)> | |
431 | as_writable_bytes(span<_Type, _Extent> __sp) noexcept | |
432 | { | |
9b8e2dea JW |
433 | auto data = reinterpret_cast<byte*>(__sp.data()); |
434 | auto size = __sp.size_bytes(); | |
435 | constexpr auto extent = _Extent == dynamic_extent | |
436 | ? dynamic_extent : _Extent * sizeof(_Type); | |
437 | return span<byte, extent>{data, size}; | |
95e9a761 JM |
438 | } |
439 | ||
b5b2e387 JW |
440 | namespace ranges |
441 | { | |
15411a64 | 442 | // Opt-in to borrowed_range concept |
b5b2e387 JW |
443 | template<typename _ElementType, size_t _Extent> |
444 | inline constexpr bool | |
15411a64 | 445 | enable_borrowed_range<span<_ElementType, _Extent>> = true; |
3841739c JW |
446 | |
447 | // Opt-in to view concept | |
448 | template<typename _ElementType, size_t _Extent> | |
449 | inline constexpr bool | |
450 | enable_view<span<_ElementType, _Extent>> | |
451 | = _Extent == 0 || _Extent == dynamic_extent; | |
b5b2e387 | 452 | } |
95e9a761 JM |
453 | _GLIBCXX_END_NAMESPACE_VERSION |
454 | } // namespace std | |
a7922ddf | 455 | #endif // concepts |
95e9a761 JM |
456 | #endif // C++20 |
457 | #endif // _GLIBCXX_SPAN |