Changeset View
Changeset View
Standalone View
Standalone View
libcxx/include/span
Show First 20 Lines • Show All 191 Lines • ▼ Show 20 Lines | concept __span_compatible_range = | ||||
ranges::sized_range<_Range> && | ranges::sized_range<_Range> && | ||||
(ranges::borrowed_range<_Range> || is_const_v<_ElementType>) && | (ranges::borrowed_range<_Range> || is_const_v<_ElementType>) && | ||||
!__is_std_span<remove_cvref_t<_Range>>::value && | !__is_std_span<remove_cvref_t<_Range>>::value && | ||||
!__is_std_array<remove_cvref_t<_Range>>::value && | !__is_std_array<remove_cvref_t<_Range>>::value && | ||||
!is_array_v<remove_cvref_t<_Range>> && | !is_array_v<remove_cvref_t<_Range>> && | ||||
is_convertible_v<remove_reference_t<ranges::range_reference_t<_Range>>(*)[], _ElementType(*)[]>; | is_convertible_v<remove_reference_t<ranges::range_reference_t<_Range>>(*)[], _ElementType(*)[]>; | ||||
#endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) | #endif // !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) | ||||
#if defined(_LIBCPP_ENABLE_DEBUG_MODE) || defined(_LIBCPP_ABI_SPAN_POINTER_ITERATORS) | |||||
# define _LIBCPP_SPAN_USE_POINTER_ITERATOR | |||||
#endif | |||||
template <typename _Tp, size_t _Extent> | template <typename _Tp, size_t _Extent> | ||||
class _LIBCPP_TEMPLATE_VIS span { | class _LIBCPP_TEMPLATE_VIS span { | ||||
public: | public: | ||||
// constants and types | // constants and types | ||||
using element_type = _Tp; | using element_type = _Tp; | ||||
using value_type = remove_cv_t<_Tp>; | using value_type = remove_cv_t<_Tp>; | ||||
using size_type = size_t; | using size_type = size_t; | ||||
using difference_type = ptrdiff_t; | using difference_type = ptrdiff_t; | ||||
using pointer = _Tp *; | using pointer = _Tp *; | ||||
using const_pointer = const _Tp *; | using const_pointer = const _Tp *; | ||||
using reference = _Tp &; | using reference = _Tp &; | ||||
using const_reference = const _Tp &; | using const_reference = const _Tp &; | ||||
#ifdef _LIBCPP_SPAN_USE_POINTER_ITERATOR | |||||
using iterator = pointer; | |||||
#else | |||||
using iterator = __wrap_iter<pointer>; | using iterator = __wrap_iter<pointer>; | ||||
#endif | |||||
using reverse_iterator = _VSTD::reverse_iterator<iterator>; | using reverse_iterator = _VSTD::reverse_iterator<iterator>; | ||||
static constexpr size_type extent = _Extent; | static constexpr size_type extent = _Extent; | ||||
// [span.cons], span constructors, copy, assignment, and destructor | // [span.cons], span constructors, copy, assignment, and destructor | ||||
template <size_t _Sz = _Extent, enable_if_t<_Sz == 0, nullptr_t> = nullptr> | template <size_t _Sz = _Extent, enable_if_t<_Sz == 0, nullptr_t> = nullptr> | ||||
_LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr} {} | _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
#ifndef _LIBCPP_ENABLE_DEBUG_MODE | |||||
constexpr span (const span&) noexcept = default; | constexpr span(const span&) noexcept = default; | ||||
#else | |||||
constexpr span(const span& __other) noexcept | |||||
: __data(__other.__data) | |||||
{ | |||||
std::__debug_db_insert_c(this); | |||||
} | |||||
#endif | |||||
constexpr span& operator=(const span&) noexcept = default; | constexpr span& operator=(const span&) noexcept = default; | ||||
template <class _It, | template <class _It, | ||||
enable_if_t<contiguous_iterator<_It> && | enable_if_t<contiguous_iterator<_It> && | ||||
is_convertible_v<remove_reference_t<iter_reference_t<_It>>(*)[], element_type (*)[]>, | is_convertible_v<remove_reference_t<iter_reference_t<_It>>(*)[], element_type (*)[]>, | ||||
nullptr_t> = nullptr> | nullptr_t> = nullptr> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr explicit span(_It __first, size_type __count) | constexpr explicit span(_It __first, size_type __count) | ||||
: __data{_VSTD::to_address(__first)} { | : __data{_VSTD::to_address(__first)} { | ||||
std::__debug_db_insert_c(this); | |||||
(void)__count; | (void)__count; | ||||
_LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (iterator, len)"); | _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (iterator, len)"); | ||||
} | } | ||||
template < | template < | ||||
class _It, class _End, | class _It, class _End, | ||||
enable_if_t<is_convertible_v<remove_reference_t<iter_reference_t<_It> > (*)[], element_type (*)[]> && | enable_if_t<is_convertible_v<remove_reference_t<iter_reference_t<_It> > (*)[], element_type (*)[]> && | ||||
contiguous_iterator<_It> && sized_sentinel_for<_End, _It> && !is_convertible_v<_End, size_t>, | contiguous_iterator<_It> && sized_sentinel_for<_End, _It> && !is_convertible_v<_End, size_t>, | ||||
nullptr_t> = nullptr> | nullptr_t> = nullptr> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr explicit span(_It __first, _End __last) : __data{_VSTD::to_address(__first)} { | constexpr explicit span(_It __first, _End __last) : __data{_VSTD::to_address(__first)} { | ||||
std::__debug_db_insert_c(this); | |||||
(void)__last; | (void)__last; | ||||
_LIBCPP_ASSERT((__last - __first >= 0), "invalid range in span's constructor (iterator, sentinel)"); | _LIBCPP_ASSERT((__last - __first >= 0), "invalid range in span's constructor (iterator, sentinel)"); | ||||
_LIBCPP_ASSERT(__last - __first == _Extent, | _LIBCPP_ASSERT(__last - __first == _Extent, | ||||
"invalid range in span's constructor (iterator, sentinel): last - first != extent"); | "invalid range in span's constructor (iterator, sentinel): last - first != extent"); | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr span(type_identity_t<element_type> (&__arr)[_Extent]) noexcept : __data{__arr} {} | _LIBCPP_INLINE_VISIBILITY constexpr span(type_identity_t<element_type> (&__arr)[_Extent]) noexcept : __data{__arr} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
template <class _OtherElementType, | template <class _OtherElementType, | ||||
enable_if_t<is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr> | enable_if_t<is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span(array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {} | constexpr span(array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
template <class _OtherElementType, | template <class _OtherElementType, | ||||
enable_if_t<is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr> | enable_if_t<is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span(const array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {} | constexpr span(const array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
#if defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) | #if defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) | ||||
template <class _Container> | template <class _Container> | ||||
requires __span_compatible_range<_Container, element_type> | requires __span_compatible_range<_Container, element_type> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr explicit span(_Container& __c) : __data{std::data(__c)} { | constexpr explicit span(_Container& __c) : __data{std::data(__c)} { | ||||
_LIBCPP_ASSERT(std::size(__c) == _Extent, "size mismatch in span's constructor (range)"); | _LIBCPP_ASSERT(std::size(__c) == _Extent, "size mismatch in span's constructor (range)"); | ||||
std::__debug_db_insert_c(this); | |||||
} | } | ||||
template <class _Container> | template <class _Container> | ||||
requires __span_compatible_range<const _Container, element_type> | requires __span_compatible_range<const _Container, element_type> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr explicit span(const _Container& __c) : __data{std::data(__c)} { | constexpr explicit span(const _Container& __c) : __data{std::data(__c)} { | ||||
_LIBCPP_ASSERT(std::size(__c) == _Extent, "size mismatch in span's constructor (range)"); | _LIBCPP_ASSERT(std::size(__c) == _Extent, "size mismatch in span's constructor (range)"); | ||||
std::__debug_db_insert_c(this); | |||||
} | } | ||||
#else | #else | ||||
template <__span_compatible_range<element_type> _Range> | template <__span_compatible_range<element_type> _Range> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr explicit span(_Range&& __r) : __data{ranges::data(__r)} { | constexpr explicit span(_Range&& __r) : __data{ranges::data(__r)} { | ||||
_LIBCPP_ASSERT(ranges::size(__r) == _Extent, "size mismatch in span's constructor (range)"); | _LIBCPP_ASSERT(ranges::size(__r) == _Extent, "size mismatch in span's constructor (range)"); | ||||
std::__debug_db_insert_c(this); | |||||
} | } | ||||
#endif | #endif | ||||
template <class _OtherElementType> | template <class _OtherElementType> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span(const span<_OtherElementType, _Extent>& __other, | constexpr span(const span<_OtherElementType, _Extent>& __other, | ||||
enable_if_t< | enable_if_t< | ||||
is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, | is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, | ||||
nullptr_t> = nullptr) | nullptr_t> = nullptr) | ||||
: __data{__other.data()} {} | : __data{__other.data()} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
template <class _OtherElementType> | template <class _OtherElementType> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr explicit span(const span<_OtherElementType, dynamic_extent>& __other, | constexpr explicit span(const span<_OtherElementType, dynamic_extent>& __other, | ||||
enable_if_t< | enable_if_t< | ||||
is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, | is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, | ||||
nullptr_t> = nullptr) noexcept | nullptr_t> = nullptr) noexcept | ||||
: __data{__other.data()} { _LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); } | : __data{__other.data()} { | ||||
std::__debug_db_insert_c(this); | |||||
_LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); | |||||
} | |||||
// ~span() noexcept = default; | #ifdef _LIBCPP_ENABLE_DEBUG_MODE | ||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 ~span() noexcept { | |||||
std::__debug_db_erase_c(this); | |||||
} | |||||
#endif | |||||
template <size_t _Count> | template <size_t _Count> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span<element_type, _Count> first() const noexcept | constexpr span<element_type, _Count> first() const noexcept | ||||
{ | { | ||||
static_assert(_Count <= _Extent, "Count out of range in span::first()"); | static_assert(_Count <= _Extent, "span<T, N>::first<Count>(): Count out of range"); | ||||
return span<element_type, _Count>{data(), _Count}; | return span<element_type, _Count>{data(), _Count}; | ||||
} | } | ||||
template <size_t _Count> | template <size_t _Count> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span<element_type, _Count> last() const noexcept | constexpr span<element_type, _Count> last() const noexcept | ||||
{ | { | ||||
static_assert(_Count <= _Extent, "Count out of range in span::last()"); | static_assert(_Count <= _Extent, "span<T, N>::last<Count>(): Count out of range"); | ||||
return span<element_type, _Count>{data() + size() - _Count, _Count}; | return span<element_type, _Count>{data() + size() - _Count, _Count}; | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept | constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(__count <= size(), "Count out of range in span::first(count)"); | _LIBCPP_ASSERT(__count <= size(), "span<T, N>::first(count): count out of range"); | ||||
return {data(), __count}; | return {data(), __count}; | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept | constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(__count <= size(), "Count out of range in span::last(count)"); | _LIBCPP_ASSERT(__count <= size(), "span<T, N>::last(count): count out of range"); | ||||
return {data() + size() - __count, __count}; | return {data() + size() - __count, __count}; | ||||
} | } | ||||
template <size_t _Offset, size_t _Count = dynamic_extent> | template <size_t _Offset, size_t _Count = dynamic_extent> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr auto subspan() const noexcept | constexpr auto subspan() const noexcept | ||||
-> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset> | -> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset> | ||||
{ | { | ||||
static_assert(_Offset <= _Extent, "Offset out of range in span::subspan()"); | static_assert(_Offset <= _Extent, "span<T, N>::subspan<Offset, Count>(): Offset out of range"); | ||||
static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset, "Offset + count out of range in span::subspan()"); | static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset, "span<T, N>::subspan<Offset, Count>(): Offset + Count out of range"); | ||||
using _ReturnType = span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>; | using _ReturnType = span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>; | ||||
return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; | return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span<element_type, dynamic_extent> | constexpr span<element_type, dynamic_extent> | ||||
subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept | subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(__offset <= size(), "Offset out of range in span::subspan(offset, count)"); | _LIBCPP_ASSERT(__offset <= size(), "span<T, N>::subspan(offset, count): offset out of range"); | ||||
_LIBCPP_ASSERT(__count <= size() || __count == dynamic_extent, "Count out of range in span::subspan(offset, count)"); | _LIBCPP_ASSERT(__count <= size() || __count == dynamic_extent, "span<T, N>::subspan(offset, count): count out of range"); | ||||
if (__count == dynamic_extent) | if (__count == dynamic_extent) | ||||
return {data() + __offset, size() - __offset}; | return {data() + __offset, size() - __offset}; | ||||
_LIBCPP_ASSERT(__count <= size() - __offset, "Offset + count out of range in span::subspan(offset, count)"); | _LIBCPP_ASSERT(__count <= size() - __offset, "span<T, N>::subspan(offset, count): offset + count out of range"); | ||||
return {data() + __offset, __count}; | return {data() + __offset, __count}; | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr size_type size() const noexcept { return _Extent; } | _LIBCPP_INLINE_VISIBILITY constexpr size_type size() const noexcept { return _Extent; } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr size_type size_bytes() const noexcept { return _Extent * sizeof(element_type); } | _LIBCPP_INLINE_VISIBILITY constexpr size_type size_bytes() const noexcept { return _Extent * sizeof(element_type); } | ||||
[[nodiscard]] _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return _Extent == 0; } | [[nodiscard]] _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return _Extent == 0; } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept | _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(__idx < size(), "span<T,N>[] index out of bounds"); | _LIBCPP_ASSERT(__idx < size(), "span<T, N>::operator[](index): index out of range"); | ||||
return __data[__idx]; | return __data[__idx]; | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept | _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(!empty(), "span<T, N>::front() on empty span"); | _LIBCPP_ASSERT(!empty(), "span<T, N>::front() on empty span"); | ||||
return __data[0]; | return __data[0]; | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept | _LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(!empty(), "span<T, N>::back() on empty span"); | _LIBCPP_ASSERT(!empty(), "span<T, N>::back() on empty span"); | ||||
return __data[size()-1]; | return __data[size()-1]; | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } | _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } | ||||
// [span.iter], span iterator support | // [span.iter], span iterator support | ||||
_LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { | _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { | ||||
#ifdef _LIBCPP_SPAN_USE_POINTER_ITERATOR | |||||
return iterator(data()); | |||||
#else | |||||
return iterator(this, data()); | return iterator(this, data()); | ||||
#endif | |||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { | _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { | ||||
#ifdef _LIBCPP_SPAN_USE_POINTER_ITERATOR | |||||
return iterator(data() + size()); | |||||
#else | |||||
return iterator(this, data() + size()); | return iterator(this, data() + size()); | ||||
#endif | |||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } | _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } | _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } | ||||
_LIBCPP_INLINE_VISIBILITY span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept | _LIBCPP_INLINE_VISIBILITY span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept | ||||
{ return span<const byte, _Extent * sizeof(element_type)>{reinterpret_cast<const byte *>(data()), size_bytes()}; } | { return span<const byte, _Extent * sizeof(element_type)>{reinterpret_cast<const byte *>(data()), size_bytes()}; } | ||||
_LIBCPP_INLINE_VISIBILITY span<byte, _Extent * sizeof(element_type)> __as_writable_bytes() const noexcept | _LIBCPP_INLINE_VISIBILITY span<byte, _Extent * sizeof(element_type)> __as_writable_bytes() const noexcept | ||||
{ return span<byte, _Extent * sizeof(element_type)>{reinterpret_cast<byte *>(data()), size_bytes()}; } | { return span<byte, _Extent * sizeof(element_type)>{reinterpret_cast<byte *>(data()), size_bytes()}; } | ||||
#ifdef _LIBCPP_ENABLE_DEBUG_MODE | |||||
using __debug_iterator = iterator; | |||||
bool __dereferenceable(const iterator* __i) const { | |||||
return __data <= __i->base() && __i->base() < __data + extent; | |||||
} | |||||
bool __decrementable(const iterator* __i) const { | |||||
return __data < __i->base() && __i->base() <= __data + extent; | |||||
} | |||||
bool __addable(const iterator* __i, ptrdiff_t __n) const { | |||||
const_pointer __p = __i->base() + __n; | |||||
return __data <= __p && __p <= __data + extent; | |||||
} | |||||
bool __subscriptable(const iterator* __i, ptrdiff_t __n) const { | |||||
const_pointer __p = __i->base() + __n; | |||||
return __data <= __p && __p < __data + extent; | |||||
} | |||||
#endif // _LIBCPP_ENABLE_DEBUG_MODE | |||||
private: | private: | ||||
pointer __data; | pointer __data; | ||||
}; | }; | ||||
template <typename _Tp> | template <typename _Tp> | ||||
class _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> { | class _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> { | ||||
private: | private: | ||||
public: | public: | ||||
// constants and types | // constants and types | ||||
using element_type = _Tp; | using element_type = _Tp; | ||||
using value_type = remove_cv_t<_Tp>; | using value_type = remove_cv_t<_Tp>; | ||||
using size_type = size_t; | using size_type = size_t; | ||||
using difference_type = ptrdiff_t; | using difference_type = ptrdiff_t; | ||||
using pointer = _Tp *; | using pointer = _Tp *; | ||||
using const_pointer = const _Tp *; | using const_pointer = const _Tp *; | ||||
using reference = _Tp &; | using reference = _Tp &; | ||||
using const_reference = const _Tp &; | using const_reference = const _Tp &; | ||||
#ifdef _LIBCPP_SPAN_USE_POINTER_ITERATOR | |||||
using iterator = pointer; | |||||
#else | |||||
using iterator = __wrap_iter<pointer>; | using iterator = __wrap_iter<pointer>; | ||||
#endif | |||||
using reverse_iterator = _VSTD::reverse_iterator<iterator>; | using reverse_iterator = _VSTD::reverse_iterator<iterator>; | ||||
static constexpr size_type extent = dynamic_extent; | static constexpr size_type extent = dynamic_extent; | ||||
// [span.cons], span constructors, copy, assignment, and destructor | // [span.cons], span constructors, copy, assignment, and destructor | ||||
_LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} {} | _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
#ifndef _LIBCPP_ENABLE_DEBUG_MODE | |||||
constexpr span (const span&) noexcept = default; | constexpr span(const span&) noexcept = default; | ||||
#else | |||||
constexpr span(const span& __other) noexcept : __data(__other.__data), __size(__other.__size) { | |||||
std::__debug_db_insert_c(this); | |||||
} | |||||
#endif | |||||
constexpr span& operator=(const span&) noexcept = default; | constexpr span& operator=(const span&) noexcept = default; | ||||
template <class _It, | template <class _It, | ||||
enable_if_t<contiguous_iterator<_It> && | enable_if_t<contiguous_iterator<_It> && | ||||
is_convertible_v<remove_reference_t<iter_reference_t<_It> > (*)[], element_type (*)[]>, | is_convertible_v<remove_reference_t<iter_reference_t<_It> > (*)[], element_type (*)[]>, | ||||
nullptr_t> = nullptr> | nullptr_t> = nullptr> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span(_It __first, size_type __count) | constexpr span(_It __first, size_type __count) | ||||
: __data{_VSTD::to_address(__first)}, __size{__count} {} | : __data{_VSTD::to_address(__first)}, __size{__count} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
template < | template < | ||||
class _It, class _End, | class _It, class _End, | ||||
enable_if_t<is_convertible_v<remove_reference_t<iter_reference_t<_It> > (*)[], element_type (*)[]> && | enable_if_t<is_convertible_v<remove_reference_t<iter_reference_t<_It> > (*)[], element_type (*)[]> && | ||||
contiguous_iterator<_It> && sized_sentinel_for<_End, _It> && !is_convertible_v<_End, size_t>, | contiguous_iterator<_It> && sized_sentinel_for<_End, _It> && !is_convertible_v<_End, size_t>, | ||||
nullptr_t> = nullptr> | nullptr_t> = nullptr> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span(_It __first, _End __last) | constexpr span(_It __first, _End __last) | ||||
: __data(_VSTD::to_address(__first)), __size(__last - __first) {} | : __data(_VSTD::to_address(__first)), __size(__last - __first) { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
template <size_t _Sz> | template <size_t _Sz> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span(type_identity_t<element_type> (&__arr)[_Sz]) noexcept : __data{__arr}, __size{_Sz} {} | constexpr span(type_identity_t<element_type> (&__arr)[_Sz]) noexcept : __data{__arr}, __size{_Sz} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
template <class _OtherElementType, size_t _Sz, | template <class _OtherElementType, size_t _Sz, | ||||
enable_if_t<is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr> | enable_if_t<is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span(array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {} | constexpr span(array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
template <class _OtherElementType, size_t _Sz, | template <class _OtherElementType, size_t _Sz, | ||||
enable_if_t<is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr> | enable_if_t<is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {} | constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
#if defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) | #if defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES) | ||||
template <class _Container> | template <class _Container> | ||||
requires __span_compatible_range<_Container, element_type> | requires __span_compatible_range<_Container, element_type> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span(_Container& __c) : __data(std::data(__c)), __size{std::size(__c)} {} | constexpr span(_Container& __c) : __data(std::data(__c)), __size{std::size(__c)} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
template <class _Container> | template <class _Container> | ||||
requires __span_compatible_range<const _Container, element_type> | requires __span_compatible_range<const _Container, element_type> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span(const _Container& __c) : __data(std::data(__c)), __size{std::size(__c)} {} | constexpr span(const _Container& __c) : __data(std::data(__c)), __size{std::size(__c)} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
#else | #else | ||||
template <__span_compatible_range<element_type> _Range> | template <__span_compatible_range<element_type> _Range> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span(_Range&& __r) : __data(ranges::data(__r)), __size{ranges::size(__r)} {} | constexpr span(_Range&& __r) : __data(ranges::data(__r)), __size{ranges::size(__r)} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
#endif | #endif | ||||
template <class _OtherElementType, size_t _OtherExtent> | template <class _OtherElementType, size_t _OtherExtent> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span(const span<_OtherElementType, _OtherExtent>& __other, | constexpr span(const span<_OtherElementType, _OtherExtent>& __other, | ||||
enable_if_t< | enable_if_t< | ||||
is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, | is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, | ||||
nullptr_t> = nullptr) noexcept | nullptr_t> = nullptr) noexcept | ||||
: __data{__other.data()}, __size{__other.size()} {} | : __data{__other.data()}, __size{__other.size()} { | ||||
std::__debug_db_insert_c(this); | |||||
} | |||||
// ~span() noexcept = default; | #ifdef _LIBCPP_ENABLE_DEBUG_MODE | ||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX17 ~span() noexcept { | |||||
std::__debug_db_erase_c(this); | |||||
} | |||||
#endif | |||||
template <size_t _Count> | template <size_t _Count> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span<element_type, _Count> first() const noexcept | constexpr span<element_type, _Count> first() const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()"); | _LIBCPP_ASSERT(_Count <= size(), "span<T>::first<Count>(): Count out of range"); | ||||
return span<element_type, _Count>{data(), _Count}; | return span<element_type, _Count>{data(), _Count}; | ||||
} | } | ||||
template <size_t _Count> | template <size_t _Count> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span<element_type, _Count> last() const noexcept | constexpr span<element_type, _Count> last() const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()"); | _LIBCPP_ASSERT(_Count <= size(), "span<T>::last<Count>(): Count out of range"); | ||||
return span<element_type, _Count>{data() + size() - _Count, _Count}; | return span<element_type, _Count>{data() + size() - _Count, _Count}; | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept | constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(__count <= size(), "Count out of range in span::first(count)"); | _LIBCPP_ASSERT(__count <= size(), "span<T>::first(count): count out of range"); | ||||
return {data(), __count}; | return {data(), __count}; | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span<element_type, dynamic_extent> last (size_type __count) const noexcept | constexpr span<element_type, dynamic_extent> last (size_type __count) const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(__count <= size(), "Count out of range in span::last(count)"); | _LIBCPP_ASSERT(__count <= size(), "span<T>::last(count): count out of range"); | ||||
return {data() + size() - __count, __count}; | return {data() + size() - __count, __count}; | ||||
} | } | ||||
template <size_t _Offset, size_t _Count = dynamic_extent> | template <size_t _Offset, size_t _Count = dynamic_extent> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
constexpr span<element_type, _Count> subspan() const noexcept | constexpr span<element_type, _Count> subspan() const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(_Offset <= size(), "Offset out of range in span::subspan()"); | _LIBCPP_ASSERT(_Offset <= size(), "span<T>::subspan<Offset, Count>(): Offset out of range"); | ||||
_LIBCPP_ASSERT(_Count == dynamic_extent || _Count <= size() - _Offset, "Offset + count out of range in span::subspan()"); | _LIBCPP_ASSERT(_Count == dynamic_extent || _Count <= size() - _Offset, "span<T>::subspan<Offset, Count>(): Offset + Count out of range"); | ||||
return span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; | return span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; | ||||
} | } | ||||
constexpr span<element_type, dynamic_extent> | constexpr span<element_type, dynamic_extent> | ||||
_LIBCPP_INLINE_VISIBILITY | _LIBCPP_INLINE_VISIBILITY | ||||
subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept | subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(__offset <= size(), "Offset out of range in span::subspan(offset, count)"); | _LIBCPP_ASSERT(__offset <= size(), "span<T>::subspan(offset, count): offset out of range"); | ||||
_LIBCPP_ASSERT(__count <= size() || __count == dynamic_extent, "count out of range in span::subspan(offset, count)"); | _LIBCPP_ASSERT(__count <= size() || __count == dynamic_extent, "span<T>::subspan(offset, count): count out of range"); | ||||
if (__count == dynamic_extent) | if (__count == dynamic_extent) | ||||
return {data() + __offset, size() - __offset}; | return {data() + __offset, size() - __offset}; | ||||
_LIBCPP_ASSERT(__count <= size() - __offset, "Offset + count out of range in span::subspan(offset, count)"); | _LIBCPP_ASSERT(__count <= size() - __offset, "span<T>::subspan(offset, count): offset + count out of range"); | ||||
return {data() + __offset, __count}; | return {data() + __offset, __count}; | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr size_type size() const noexcept { return __size; } | _LIBCPP_INLINE_VISIBILITY constexpr size_type size() const noexcept { return __size; } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr size_type size_bytes() const noexcept { return __size * sizeof(element_type); } | _LIBCPP_INLINE_VISIBILITY constexpr size_type size_bytes() const noexcept { return __size * sizeof(element_type); } | ||||
[[nodiscard]] _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return __size == 0; } | [[nodiscard]] _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return __size == 0; } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept | _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(__idx < size(), "span<T>[] index out of bounds"); | _LIBCPP_ASSERT(__idx < size(), "span<T>::operator[](index): index out of range"); | ||||
return __data[__idx]; | return __data[__idx]; | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept | _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(!empty(), "span<T>[].front() on empty span"); | _LIBCPP_ASSERT(!empty(), "span<T>::front() on empty span"); | ||||
return __data[0]; | return __data[0]; | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept | _LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept | ||||
{ | { | ||||
_LIBCPP_ASSERT(!empty(), "span<T>[].back() on empty span"); | _LIBCPP_ASSERT(!empty(), "span<T>::back() on empty span"); | ||||
return __data[size()-1]; | return __data[size()-1]; | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } | _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } | ||||
// [span.iter], span iterator support | // [span.iter], span iterator support | ||||
_LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { | _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { | ||||
#ifdef _LIBCPP_SPAN_USE_POINTER_ITERATOR | |||||
return iterator(data()); | |||||
#else | |||||
return iterator(this, data()); | return iterator(this, data()); | ||||
#endif | |||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { | _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { | ||||
#ifdef _LIBCPP_SPAN_USE_POINTER_ITERATOR | |||||
return iterator(data() + size()); | |||||
#else | |||||
return iterator(this, data() + size()); | return iterator(this, data() + size()); | ||||
#endif | |||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } | _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } | _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } | ||||
_LIBCPP_INLINE_VISIBILITY span<const byte, dynamic_extent> __as_bytes() const noexcept | _LIBCPP_INLINE_VISIBILITY span<const byte, dynamic_extent> __as_bytes() const noexcept | ||||
{ return {reinterpret_cast<const byte *>(data()), size_bytes()}; } | { return {reinterpret_cast<const byte *>(data()), size_bytes()}; } | ||||
_LIBCPP_INLINE_VISIBILITY span<byte, dynamic_extent> __as_writable_bytes() const noexcept | _LIBCPP_INLINE_VISIBILITY span<byte, dynamic_extent> __as_writable_bytes() const noexcept | ||||
{ return {reinterpret_cast<byte *>(data()), size_bytes()}; } | { return {reinterpret_cast<byte *>(data()), size_bytes()}; } | ||||
#ifdef _LIBCPP_ENABLE_DEBUG_MODE | |||||
using __debug_iterator = iterator; | |||||
bool __dereferenceable(const iterator* __i) const { | |||||
return __data <= __i->base() && __i->base() < __data + __size; | |||||
} | |||||
bool __decrementable(const iterator* __i) const { | |||||
return __data < __i->base() && __i->base() <= __data + __size; | |||||
} | |||||
bool __addable(const iterator* __i, ptrdiff_t __n) const { | |||||
const_pointer __p = __i->base() + __n; | |||||
return __data <= __p && __p <= __data + __size; | |||||
} | |||||
bool __subscriptable(const iterator* __i, ptrdiff_t __n) const { | |||||
const_pointer __p = __i->base() + __n; | |||||
return __data <= __p && __p < __data + __size; | |||||
} | |||||
#endif // _LIBCPP_ENABLE_DEBUG_MODE | |||||
private: | private: | ||||
pointer __data; | pointer __data; | ||||
size_type __size; | size_type __size; | ||||
}; | }; | ||||
template <class _Tp, size_t _Extent> | template <class _Tp, size_t _Extent> | ||||
inline constexpr bool ranges::enable_borrowed_range<span<_Tp, _Extent> > = true; | inline constexpr bool ranges::enable_borrowed_range<span<_Tp, _Extent> > = true; | ||||
▲ Show 20 Lines • Show All 48 Lines • Show Last 20 Lines |