Changeset View
Changeset View
Standalone View
Standalone View
libcxx/include/span
Show First 20 Lines • Show All 125 Lines • ▼ Show 20 Lines | |||||
} // namespace std | } // namespace std | ||||
*/ | */ | ||||
#include <__assert> // all public C++ headers provide the assertion handler | #include <__assert> // all public C++ headers provide the assertion handler | ||||
#include <__config> | #include <__config> | ||||
#include <__debug> | #include <__debug> | ||||
#include <__fwd/span.h> | #include <__fwd/span.h> | ||||
#include <__iterator/bounded_iter.h> | |||||
#include <__iterator/concepts.h> | #include <__iterator/concepts.h> | ||||
#include <__iterator/iterator_traits.h> | #include <__iterator/iterator_traits.h> | ||||
#include <__iterator/wrap_iter.h> | #include <__iterator/wrap_iter.h> | ||||
#include <__memory/pointer_traits.h> | #include <__memory/pointer_traits.h> | ||||
#include <__ranges/concepts.h> | #include <__ranges/concepts.h> | ||||
#include <__ranges/data.h> | #include <__ranges/data.h> | ||||
#include <__ranges/enable_borrowed_range.h> | #include <__ranges/enable_borrowed_range.h> | ||||
#include <__ranges/enable_view.h> | #include <__ranges/enable_view.h> | ||||
▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | |||||
concept __span_array_convertible = is_convertible_v<_From(*)[], _To(*)[]>; | concept __span_array_convertible = is_convertible_v<_From(*)[], _To(*)[]>; | ||||
template <class _It, class _Tp> | template <class _It, class _Tp> | ||||
concept __span_compatible_iterator = contiguous_iterator<_It> && __span_array_convertible<remove_reference_t<iter_reference_t<_It>>, _Tp>; | concept __span_compatible_iterator = contiguous_iterator<_It> && __span_array_convertible<remove_reference_t<iter_reference_t<_It>>, _Tp>; | ||||
template <class _Sentinel, class _It> | template <class _Sentinel, class _It> | ||||
concept __span_compatible_sentinel_for = sized_sentinel_for<_Sentinel, _It> && !is_convertible_v<_Sentinel, size_t>; | concept __span_compatible_sentinel_for = sized_sentinel_for<_Sentinel, _It> && !is_convertible_v<_Sentinel, size_t>; | ||||
#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 | #ifdef _LIBCPP_ENABLE_DEBUG_MODE | ||||
using iterator = pointer; | using iterator = __bounded_iter<pointer>; | ||||
philnik: What do you think about introducing a `constexpr bool _InDebugMode` and make this `using… | |||||
I am ambivalent about this. I don't think it's a bad idea, but I'm not sure there is much of an actual benefit beyond being more "modern". I'll give it a shot and report on what I think. ldionne: I am ambivalent about this. I don't think it's a bad idea, but I'm not sure there is much of an… | |||||
#else | #else | ||||
using iterator = __wrap_iter<pointer>; | using iterator = __wrap_iter<pointer>; | ||||
#endif | #endif | ||||
using reverse_iterator = _VSTD::reverse_iterator<iterator>; | using reverse_iterator = _VSTD::reverse_iterator<iterator>; | ||||
This gets rbegin() and rend() covered as well, right? Shall we add some tests to make the guarantee explicit? jkorous: This gets `rbegin()` and `rend()` covered as well, right? Shall we add some tests to make the… | |||||
Yes, it covers it. Added tests. ldionne: Yes, it covers it. Added tests. | |||||
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> requires(_Sz == 0) | template <size_t _Sz = _Extent> requires(_Sz == 0) | ||||
_LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr} {} | _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr} {} | ||||
constexpr span (const span&) noexcept = default; | constexpr span (const span&) noexcept = default; | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | |||||
// ~span() noexcept = default; | // ~span() noexcept = default; | ||||
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 | #ifdef _LIBCPP_ENABLE_DEBUG_MODE | ||||
return iterator(data()); | return std::__make_bounded_iter(data(), data(), data() + size()); | ||||
#else | #else | ||||
return iterator(this, data()); | return iterator(this, data()); | ||||
#endif | #endif | ||||
Not Done ReplyInline ActionsFor example this could change to if constexpr (_InDebugMode) { return iterator(data(), data(), data() + size()); } else { return iterator(this, data()); } philnik: For example this could change to
```
if constexpr (_InDebugMode) {
return… | |||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { | _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { | ||||
#ifdef _LIBCPP_SPAN_USE_POINTER_ITERATOR | #ifdef _LIBCPP_ENABLE_DEBUG_MODE | ||||
return iterator(data() + size()); | return std::__make_bounded_iter(data() + size(), data(), data() + size()); | ||||
#else | #else | ||||
return iterator(this, data() + size()); | return iterator(this, data() + size()); | ||||
#endif | #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 | ||||
Show All 14 Lines | // 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 | #ifdef _LIBCPP_ENABLE_DEBUG_MODE | ||||
using iterator = pointer; | using iterator = __bounded_iter<pointer>; | ||||
#else | #else | ||||
using iterator = __wrap_iter<pointer>; | using iterator = __wrap_iter<pointer>; | ||||
#endif | #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 | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | _LIBCPP_INLINE_VISIBILITY | ||||
: __data{__other.data()}, __size{__other.size()} {} | : __data{__other.data()}, __size{__other.size()} {} | ||||
// ~span() noexcept = default; | // ~span() noexcept = default; | ||||
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 | #ifdef _LIBCPP_ENABLE_DEBUG_MODE | ||||
return iterator(data()); | return std::__make_bounded_iter(data(), data(), data() + size()); | ||||
#else | #else | ||||
return iterator(this, data()); | return iterator(this, data()); | ||||
#endif | #endif | ||||
} | } | ||||
_LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { | _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { | ||||
#ifdef _LIBCPP_SPAN_USE_POINTER_ITERATOR | #ifdef _LIBCPP_ENABLE_DEBUG_MODE | ||||
return iterator(data() + size()); | return std::__make_bounded_iter(data() + size(), data(), data() + size()); | ||||
#else | #else | ||||
return iterator(this, data() + size()); | return iterator(this, data() + size()); | ||||
#endif | #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 | ||||
▲ Show 20 Lines • Show All 59 Lines • Show Last 20 Lines |
What do you think about introducing a constexpr bool _InDebugMode and make this using iterator = _If<_InDebugMode, __bounded_iter<pointer>, __wrap_iter<pointer>>? With that it would also be possible to use if constexpr (_InDebugMode) and void func() requires _InDebugMode. This only works for C++11, C++17 and C++20 code respectively, but is a lot nicer to read IMO.