blob: 774f69823bd0cd31ae0350a12ead81841f2b87d0 [file] [log] [blame]
Marshall Clowd2ad87e2018-07-24 03:01:02 +00001// -*- C++ -*-
2//===------------------------------ span ---------------------------------===//
3//
Chandler Carruthd2012102019-01-19 10:56:40 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Marshall Clowd2ad87e2018-07-24 03:01:02 +00007//
8//===---------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_SPAN
11#define _LIBCPP_SPAN
12
13/*
14 span synopsis
15
16namespace std {
17
18// constants
19inline constexpr ptrdiff_t dynamic_extent = -1;
20
21// [views.span], class template span
22template <class ElementType, ptrdiff_t Extent = dynamic_extent>
23 class span;
24
Marshall Clowd2ad87e2018-07-24 03:01:02 +000025// [span.objectrep], views of object representation
26template <class ElementType, ptrdiff_t Extent>
Louis Dionne44bcff92018-08-03 22:36:53 +000027 span<const byte, ((Extent == dynamic_extent) ? dynamic_extent :
Marshall Clowd2ad87e2018-07-24 03:01:02 +000028 (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept;
29
30template <class ElementType, ptrdiff_t Extent>
Louis Dionne44bcff92018-08-03 22:36:53 +000031 span< byte, ((Extent == dynamic_extent) ? dynamic_extent :
Marshall Clowd2ad87e2018-07-24 03:01:02 +000032 (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept;
33
34
35namespace std {
36template <class ElementType, ptrdiff_t Extent = dynamic_extent>
37class span {
38public:
39 // constants and types
40 using element_type = ElementType;
41 using value_type = remove_cv_t<ElementType>;
42 using index_type = ptrdiff_t;
43 using difference_type = ptrdiff_t;
44 using pointer = element_type*;
45 using reference = element_type&;
46 using iterator = implementation-defined;
47 using const_iterator = implementation-defined;
48 using reverse_iterator = std::reverse_iterator<iterator>;
49 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
50 static constexpr index_type extent = Extent;
51
52 // [span.cons], span constructors, copy, assignment, and destructor
53 constexpr span() noexcept;
54 constexpr span(pointer ptr, index_type count);
55 constexpr span(pointer firstElem, pointer lastElem);
56 template <size_t N>
57 constexpr span(element_type (&arr)[N]) noexcept;
58 template <size_t N>
59 constexpr span(array<value_type, N>& arr) noexcept;
60 template <size_t N>
61 constexpr span(const array<value_type, N>& arr) noexcept;
62 template <class Container>
63 constexpr span(Container& cont);
64 template <class Container>
65 constexpr span(const Container& cont);
66 constexpr span(const span& other) noexcept = default;
67 template <class OtherElementType, ptrdiff_t OtherExtent>
68 constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept;
69 ~span() noexcept = default;
70 constexpr span& operator=(const span& other) noexcept = default;
71
72 // [span.sub], span subviews
73 template <ptrdiff_t Count>
74 constexpr span<element_type, Count> first() const;
75 template <ptrdiff_t Count>
76 constexpr span<element_type, Count> last() const;
77 template <ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent>
78 constexpr span<element_type, see below> subspan() const;
79
80 constexpr span<element_type, dynamic_extent> first(index_type count) const;
81 constexpr span<element_type, dynamic_extent> last(index_type count) const;
82 constexpr span<element_type, dynamic_extent> subspan(index_type offset, index_type count = dynamic_extent) const;
83
84 // [span.obs], span observers
85 constexpr index_type size() const noexcept;
86 constexpr index_type size_bytes() const noexcept;
87 constexpr bool empty() const noexcept;
88
89 // [span.elem], span element access
90 constexpr reference operator[](index_type idx) const;
91 constexpr reference operator()(index_type idx) const;
92 constexpr pointer data() const noexcept;
93
94 // [span.iterators], span iterator support
95 constexpr iterator begin() const noexcept;
96 constexpr iterator end() const noexcept;
97 constexpr const_iterator cbegin() const noexcept;
98 constexpr const_iterator cend() const noexcept;
99 constexpr reverse_iterator rbegin() const noexcept;
100 constexpr reverse_iterator rend() const noexcept;
101 constexpr const_reverse_iterator crbegin() const noexcept;
102 constexpr const_reverse_iterator crend() const noexcept;
103
104private:
105 pointer data_; // exposition only
106 index_type size_; // exposition only
107};
108
109template<class T, size_t N>
110 span(T (&)[N]) -> span<T, N>;
Louis Dionne44bcff92018-08-03 22:36:53 +0000111
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000112template<class T, size_t N>
113 span(array<T, N>&) -> span<T, N>;
114
115template<class T, size_t N>
116 span(const array<T, N>&) -> span<const T, N>;
117
118template<class Container>
119 span(Container&) -> span<typename Container::value_type>;
120
121template<class Container>
122 span(const Container&) -> span<const typename Container::value_type>;
123
124} // namespace std
125
126*/
127
Marshall Clow8dc3ea12018-07-24 03:56:38 +0000128#include <__config>
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000129#include <cstddef> // for ptrdiff_t
130#include <iterator> // for iterators
131#include <array> // for array
132#include <type_traits> // for remove_cv, etc
133#include <cstddef> // for byte
134
135#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
136#pragma GCC system_header
137#endif
138
139_LIBCPP_BEGIN_NAMESPACE_STD
140
141#if _LIBCPP_STD_VER > 17
142
143inline constexpr ptrdiff_t dynamic_extent = -1;
144template <typename _Tp, ptrdiff_t _Extent = dynamic_extent> class span;
145
146
147template <class _Tp>
148struct __is_span_impl : public false_type {};
149
150template <class _Tp, ptrdiff_t _Extent>
151struct __is_span_impl<span<_Tp, _Extent>> : public true_type {};
152
153template <class _Tp>
154struct __is_span : public __is_span_impl<remove_cv_t<_Tp>> {};
155
156template <class _Tp>
157struct __is_std_array_impl : public false_type {};
158
159template <class _Tp, size_t _Sz>
160struct __is_std_array_impl<array<_Tp, _Sz>> : public true_type {};
161
162template <class _Tp>
163struct __is_std_array : public __is_std_array_impl<remove_cv_t<_Tp>> {};
164
165template <class _Tp, class _ElementType, class = void>
166struct __is_span_compatible_container : public false_type {};
167
168template <class _Tp, class _ElementType>
169struct __is_span_compatible_container<_Tp, _ElementType,
170 void_t<
171 // is not a specialization of span
172 typename enable_if<!__is_span<_Tp>::value, nullptr_t>::type,
173 // is not a specialization of array
174 typename enable_if<!__is_std_array<_Tp>::value, nullptr_t>::type,
175 // is_array_v<Container> is false,
176 typename enable_if<!is_array_v<_Tp>, nullptr_t>::type,
177 // data(cont) and size(cont) are well formed
178 decltype(data(declval<_Tp>())),
179 decltype(size(declval<_Tp>())),
180 // remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[]
181 typename enable_if<
Louis Dionne44bcff92018-08-03 22:36:53 +0000182 is_convertible_v<remove_pointer_t<decltype(data(declval<_Tp &>()))>(*)[],
183 _ElementType(*)[]>,
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000184 nullptr_t>::type
185 >>
186 : public true_type {};
187
188
189template <typename _Tp, ptrdiff_t _Extent>
190class _LIBCPP_TEMPLATE_VIS span {
191public:
192// constants and types
193 using element_type = _Tp;
194 using value_type = remove_cv_t<_Tp>;
195 using index_type = ptrdiff_t;
196 using difference_type = ptrdiff_t;
197 using pointer = _Tp *;
198 using const_pointer = const _Tp *; // not in standard
199 using reference = _Tp &;
200 using const_reference = const _Tp &; // not in standard
201 using iterator = __wrap_iter<pointer>;
202 using const_iterator = __wrap_iter<const_pointer>;
203 using reverse_iterator = _VSTD::reverse_iterator<iterator>;
204 using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>;
205
206 static constexpr index_type extent = _Extent;
207 static_assert (_Extent >= 0, "Can't have a span with an extent < 0");
208
Louis Dionne44bcff92018-08-03 22:36:53 +0000209// [span.cons], span constructors, copy, assignment, and destructor
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000210 _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}
211 { static_assert(_Extent == 0, "Can't default construct a statically sized span with size > 0"); }
212
213 constexpr span (const span&) noexcept = default;
214 constexpr span& operator=(const span&) noexcept = default;
215
216 _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr}
217 { (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); }
218 _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}
219 { (void)__l; _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); }
220
221 _LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent]) noexcept : __data{__arr} {}
222 _LIBCPP_INLINE_VISIBILITY constexpr span( array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {}
223 _LIBCPP_INLINE_VISIBILITY constexpr span(const array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {}
224
225 template <class _Container>
226 inline _LIBCPP_INLINE_VISIBILITY
227 constexpr span( _Container& __c,
228 enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
229 : __data{_VSTD::data(__c)}
Louis Dionne0ba926d2018-10-03 21:36:16 +0000230 { _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (container)"); }
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000231
232 template <class _Container>
233 inline _LIBCPP_INLINE_VISIBILITY
234 constexpr span(const _Container& __c,
235 enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
236 : __data{_VSTD::data(__c)}
237 { _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (const container)"); }
238
239 template <class _OtherElementType>
240 inline _LIBCPP_INLINE_VISIBILITY
241 constexpr span(const span<_OtherElementType, _Extent>& __other,
242 enable_if_t<
243 is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
244 nullptr_t> = nullptr)
245 : __data{__other.data()} {}
246
247 template <class _OtherElementType>
248 inline _LIBCPP_INLINE_VISIBILITY
249 constexpr span(const span<_OtherElementType, dynamic_extent>& __other,
250 enable_if_t<
251 is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
252 nullptr_t> = nullptr) noexcept
253 : __data{__other.data()} { _LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); }
254
255
256// ~span() noexcept = default;
257
258 template <ptrdiff_t _Count>
259 inline _LIBCPP_INLINE_VISIBILITY
260 constexpr span<element_type, _Count> first() const noexcept
261 {
262 static_assert(_Count >= 0, "Count must be >= 0 in span::first()");
263 static_assert(_Count <= _Extent, "Count out of range in span::first()");
264 return {data(), _Count};
265 }
266
267 template <ptrdiff_t _Count>
268 inline _LIBCPP_INLINE_VISIBILITY
269 constexpr span<element_type, _Count> last() const noexcept
270 {
271 static_assert(_Count >= 0, "Count must be >= 0 in span::last()");
272 static_assert(_Count <= _Extent, "Count out of range in span::last()");
273 return {data() + size() - _Count, _Count};
274 }
Louis Dionne44bcff92018-08-03 22:36:53 +0000275
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000276 _LIBCPP_INLINE_VISIBILITY
277 constexpr span<element_type, dynamic_extent> first(index_type __count) const noexcept
278 {
279 _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::first(count)");
280 return {data(), __count};
281 }
282
283 _LIBCPP_INLINE_VISIBILITY
284 constexpr span<element_type, dynamic_extent> last(index_type __count) const noexcept
285 {
286 _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::last(count)");
287 return {data() + size() - __count, __count};
288 }
289
290 template <ptrdiff_t _Offset, ptrdiff_t _Count = dynamic_extent>
291 inline _LIBCPP_INLINE_VISIBILITY
292 constexpr auto subspan() const noexcept
293 -> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>
294 {
295 _LIBCPP_ASSERT(_Offset >= 0 && _Offset <= size(), "Offset out of range in span::subspan()");
296 return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
297 }
298
299
300 inline _LIBCPP_INLINE_VISIBILITY
301 constexpr span<element_type, dynamic_extent>
302 subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept
Louis Dionne44bcff92018-08-03 22:36:53 +0000303 {
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000304 _LIBCPP_ASSERT( __offset >= 0 && __offset <= size(), "Offset out of range in span::subspan(offset, count)");
305 _LIBCPP_ASSERT((__count >= 0 && __count <= size()) || __count == dynamic_extent, "Count out of range in span::subspan(offset, count)");
306 if (__count == dynamic_extent)
307 return {data() + __offset, size() - __offset};
308 _LIBCPP_ASSERT(__offset + __count <= size(), "count + offset out of range in span::subspan(offset, count)");
309 return {data() + __offset, __count};
310 }
311
312 _LIBCPP_INLINE_VISIBILITY constexpr index_type size() const noexcept { return _Extent; }
313 _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return _Extent * sizeof(element_type); }
314 _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return _Extent == 0; }
315
316 _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept
317 {
318 _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T,N>[] index out of bounds");
Louis Dionne44bcff92018-08-03 22:36:53 +0000319 return __data[__idx];
320 }
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000321
322 _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept
323 {
324 _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T,N>() index out of bounds");
Louis Dionne44bcff92018-08-03 22:36:53 +0000325 return __data[__idx];
326 }
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000327
328 _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; }
329
330// [span.iter], span iterator support
331 _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); }
332 _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); }
333 _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); }
334 _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); }
335 _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
336 _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
337 _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
338 _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
339
340 _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept
341 {
342 pointer __p = __data;
343 __data = __other.__data;
344 __other.__data = __p;
345 }
Louis Dionne44bcff92018-08-03 22:36:53 +0000346
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000347 _LIBCPP_INLINE_VISIBILITY span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept
348 { return {reinterpret_cast<const byte *>(data()), size_bytes()}; }
349
350 _LIBCPP_INLINE_VISIBILITY span<byte, _Extent * sizeof(element_type)> __as_writeable_bytes() const noexcept
351 { return {reinterpret_cast<byte *>(data()), size_bytes()}; }
352
353private:
354 pointer __data;
355
356};
357
358
359template <typename _Tp>
360class _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> {
361private:
362
363public:
364// constants and types
365 using element_type = _Tp;
366 using value_type = remove_cv_t<_Tp>;
367 using index_type = ptrdiff_t;
368 using difference_type = ptrdiff_t;
369 using pointer = _Tp *;
370 using const_pointer = const _Tp *; // not in standard
371 using reference = _Tp &;
372 using const_reference = const _Tp &; // not in standard
373 using iterator = __wrap_iter<pointer>;
374 using const_iterator = __wrap_iter<const_pointer>;
375 using reverse_iterator = _VSTD::reverse_iterator<iterator>;
376 using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>;
377
378 static constexpr index_type extent = dynamic_extent;
379
Louis Dionne44bcff92018-08-03 22:36:53 +0000380// [span.cons], span constructors, copy, assignment, and destructor
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000381 _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} {}
382
383 constexpr span (const span&) noexcept = default;
384 constexpr span& operator=(const span&) noexcept = default;
385
386 _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr}, __size{__count} {}
387 _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{distance(__f, __l)} {}
388
389 template <size_t _Sz>
390 inline _LIBCPP_INLINE_VISIBILITY
391 constexpr span(element_type (&__arr)[_Sz]) noexcept : __data{__arr}, __size{_Sz} {}
392
393 template <size_t _Sz>
394 inline _LIBCPP_INLINE_VISIBILITY
395 constexpr span(array<value_type, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
Louis Dionne44bcff92018-08-03 22:36:53 +0000396
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000397 template <size_t _Sz>
398 inline _LIBCPP_INLINE_VISIBILITY
399 constexpr span(const array<value_type, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
400
401 template <class _Container>
402 inline _LIBCPP_INLINE_VISIBILITY
403 constexpr span( _Container& __c,
404 enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
405 : __data{_VSTD::data(__c)}, __size{(index_type) _VSTD::size(__c)} {}
406
407 template <class _Container>
408 inline _LIBCPP_INLINE_VISIBILITY
409 constexpr span(const _Container& __c,
410 enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
411 : __data{_VSTD::data(__c)}, __size{(index_type) _VSTD::size(__c)} {}
412
413
414 template <class _OtherElementType, ptrdiff_t _OtherExtent>
415 inline _LIBCPP_INLINE_VISIBILITY
416 constexpr span(const span<_OtherElementType, _OtherExtent>& __other,
417 enable_if_t<
418 is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
419 nullptr_t> = nullptr) noexcept
420 : __data{__other.data()}, __size{__other.size()} {}
421
422// ~span() noexcept = default;
423
424 template <ptrdiff_t _Count>
425 inline _LIBCPP_INLINE_VISIBILITY
426 constexpr span<element_type, _Count> first() const noexcept
427 {
Louis Dionne0ba926d2018-10-03 21:36:16 +0000428 static_assert(_Count >= 0, "Count must be >= 0 in span::first()");
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000429 _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()");
430 return {data(), _Count};
431 }
432
433 template <ptrdiff_t _Count>
434 inline _LIBCPP_INLINE_VISIBILITY
435 constexpr span<element_type, _Count> last() const noexcept
436 {
Louis Dionne0ba926d2018-10-03 21:36:16 +0000437 static_assert(_Count >= 0, "Count must be >= 0 in span::last()");
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000438 _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()");
439 return {data() + size() - _Count, _Count};
440 }
441
442 _LIBCPP_INLINE_VISIBILITY
443 constexpr span<element_type, dynamic_extent> first(index_type __count) const noexcept
444 {
445 _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::first(count)");
446 return {data(), __count};
447 }
Louis Dionne44bcff92018-08-03 22:36:53 +0000448
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000449 _LIBCPP_INLINE_VISIBILITY
450 constexpr span<element_type, dynamic_extent> last (index_type __count) const noexcept
451 {
452 _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::last(count)");
453 return {data() + size() - __count, __count};
454 }
455
456 template <ptrdiff_t _Offset, ptrdiff_t _Count = dynamic_extent>
457 inline _LIBCPP_INLINE_VISIBILITY
458 constexpr span<_Tp, dynamic_extent> subspan() const noexcept
459 {
460 _LIBCPP_ASSERT(_Offset >= 0 && _Offset <= size(), "Offset out of range in span::subspan()");
461 _LIBCPP_ASSERT(_Count == dynamic_extent || _Offset + _Count <= size(), "Count out of range in span::subspan()");
462 return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
463 }
464
465 constexpr span<element_type, dynamic_extent>
466 inline _LIBCPP_INLINE_VISIBILITY
467 subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept
Louis Dionne44bcff92018-08-03 22:36:53 +0000468 {
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000469 _LIBCPP_ASSERT( __offset >= 0 && __offset <= size(), "Offset out of range in span::subspan(offset, count)");
470 _LIBCPP_ASSERT((__count >= 0 && __count <= size()) || __count == dynamic_extent, "count out of range in span::subspan(offset, count)");
471 if (__count == dynamic_extent)
472 return {data() + __offset, size() - __offset};
473 _LIBCPP_ASSERT(__offset + __count <= size(), "Offset + count out of range in span::subspan(offset, count)");
474 return {data() + __offset, __count};
475 }
476
477 _LIBCPP_INLINE_VISIBILITY constexpr index_type size() const noexcept { return __size; }
478 _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return __size * sizeof(element_type); }
479 _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return __size == 0; }
480
481 _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept
482 {
483 _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T>[] index out of bounds");
Louis Dionne44bcff92018-08-03 22:36:53 +0000484 return __data[__idx];
485 }
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000486
487 _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept
488 {
489 _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T>() index out of bounds");
Louis Dionne44bcff92018-08-03 22:36:53 +0000490 return __data[__idx];
491 }
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000492
493 _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; }
494
495// [span.iter], span iterator support
496 _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); }
497 _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); }
498 _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); }
499 _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); }
500 _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
501 _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
502 _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); }
503 _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); }
504
505 _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept
506 {
507 pointer __p = __data;
508 __data = __other.__data;
509 __other.__data = __p;
510
511 index_type __sz = __size;
512 __size = __other.__size;
513 __other.__size = __sz;
514 }
515
516 _LIBCPP_INLINE_VISIBILITY span<const byte, dynamic_extent> __as_bytes() const noexcept
517 { return {reinterpret_cast<const byte *>(data()), size_bytes()}; }
518
519 _LIBCPP_INLINE_VISIBILITY span<byte, dynamic_extent> __as_writeable_bytes() const noexcept
520 { return {reinterpret_cast<byte *>(data()), size_bytes()}; }
521
522private:
523 pointer __data;
524 index_type __size;
525};
526
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000527// as_bytes & as_writeable_bytes
528template <class _Tp, ptrdiff_t _Extent>
Louis Dionne44bcff92018-08-03 22:36:53 +0000529 auto as_bytes(span<_Tp, _Extent> __s) noexcept
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000530 -> decltype(__s.__as_bytes())
531 { return __s.__as_bytes(); }
532
533template <class _Tp, ptrdiff_t _Extent>
534 auto as_writeable_bytes(span<_Tp, _Extent> __s) noexcept
535 -> typename enable_if<!is_const_v<_Tp>, decltype(__s.__as_writeable_bytes())>::type
536 { return __s.__as_writeable_bytes(); }
537
538template <class _Tp, ptrdiff_t _Extent>
539 constexpr void swap(span<_Tp, _Extent> &__lhs, span<_Tp, _Extent> &__rhs) noexcept
540 { __lhs.swap(__rhs); }
541
542
543// Deduction guides
544template<class _Tp, size_t _Sz>
545 span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>;
Louis Dionne44bcff92018-08-03 22:36:53 +0000546
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000547template<class _Tp, size_t _Sz>
548 span(array<_Tp, _Sz>&) -> span<_Tp, _Sz>;
549
550template<class _Tp, size_t _Sz>
551 span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>;
552
553template<class _Container>
554 span(_Container&) -> span<typename _Container::value_type>;
555
556template<class _Container>
557 span(const _Container&) -> span<const typename _Container::value_type>;
558
Marshall Clow8dc3ea12018-07-24 03:56:38 +0000559#endif // _LIBCPP_STD_VER > 17
560
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000561_LIBCPP_END_NAMESPACE_STD
562
Marshall Clowd2ad87e2018-07-24 03:01:02 +0000563#endif // _LIBCPP_SPAN