
libc++ has started splicing standard library headers into much more fine-grained content for maintainability. It's very likely that outdated and naive tooling (some of which is outside of LLVM's scope) will suggest users include things such as `<__algorithm/find.h>` instead of `<algorithm>`, and Hyrum's law suggests that users will eventually begin to rely on this without the help of tooling. As such, this commit intends to protect users from themselves, by making it a hard error for anyone outside of the standard library to include libc++ detail headers. This is the first of four patches. Patch #2 will solve the problem for pre-processor `#include`s; patches #3 and #4 will solve the problem for `<__tree>` and `<__hash_table>` (since I've never touched the test cases that are failing for these two, I want to split them out into their own commits to be extra careful). Patch #5 will concern itself with `<__threading_support>`, which intersects with libcxxabi (which I know even less about). Differential Revision: https://reviews.llvm.org/D105932
582 lines
24 KiB
C++
582 lines
24 KiB
C++
// -*- C++ -*-
|
|
//===------------------------------ span ---------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===---------------------------------------------------------------------===//
|
|
|
|
#ifndef _LIBCPP_SPAN
|
|
#define _LIBCPP_SPAN
|
|
|
|
/*
|
|
span synopsis
|
|
|
|
namespace std {
|
|
|
|
// constants
|
|
inline constexpr size_t dynamic_extent = numeric_limits<size_t>::max();
|
|
|
|
// [views.span], class template span
|
|
template <class ElementType, size_t Extent = dynamic_extent>
|
|
class span;
|
|
|
|
template<class ElementType, size_t Extent>
|
|
inline constexpr bool ranges::enable_view<span<ElementType, Extent>> = true;
|
|
|
|
template<class ElementType, size_t Extent>
|
|
inline constexpr bool ranges::enable_borrowed_range<span<ElementType, Extent>> = true;
|
|
|
|
// [span.objectrep], views of object representation
|
|
template <class ElementType, size_t Extent>
|
|
span<const byte, ((Extent == dynamic_extent) ? dynamic_extent :
|
|
(sizeof(ElementType) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept;
|
|
|
|
template <class ElementType, size_t Extent>
|
|
span< byte, ((Extent == dynamic_extent) ? dynamic_extent :
|
|
(sizeof(ElementType) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept;
|
|
|
|
|
|
template <class ElementType, size_t Extent = dynamic_extent>
|
|
class span {
|
|
public:
|
|
// constants and types
|
|
using element_type = ElementType;
|
|
using value_type = remove_cv_t<ElementType>;
|
|
using size_type = size_t;
|
|
using difference_type = ptrdiff_t;
|
|
using pointer = element_type*;
|
|
using const_pointer = const element_type*;
|
|
using reference = element_type&;
|
|
using const_reference = const element_type&;
|
|
using iterator = implementation-defined;
|
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
static constexpr size_type extent = Extent;
|
|
|
|
// [span.cons], span constructors, copy, assignment, and destructor
|
|
constexpr span() noexcept;
|
|
constexpr explicit(Extent != dynamic_extent) span(pointer ptr, size_type count);
|
|
constexpr explicit(Extent != dynamic_extent) span(pointer firstElem, pointer lastElem);
|
|
template <size_t N>
|
|
constexpr span(element_type (&arr)[N]) noexcept;
|
|
template <size_t N>
|
|
constexpr span(array<value_type, N>& arr) noexcept;
|
|
template <size_t N>
|
|
constexpr span(const array<value_type, N>& arr) noexcept;
|
|
template <class Container>
|
|
constexpr explicit(Extent != dynamic_extent) span(Container& cont);
|
|
template <class Container>
|
|
constexpr explicit(Extent != dynamic_extent) span(const Container& cont);
|
|
constexpr span(const span& other) noexcept = default;
|
|
template <class OtherElementType, size_t OtherExtent>
|
|
constexpr explicit(Extent != dynamic_extent) span(const span<OtherElementType, OtherExtent>& s) noexcept;
|
|
~span() noexcept = default;
|
|
constexpr span& operator=(const span& other) noexcept = default;
|
|
|
|
// [span.sub], span subviews
|
|
template <size_t Count>
|
|
constexpr span<element_type, Count> first() const;
|
|
template <size_t Count>
|
|
constexpr span<element_type, Count> last() const;
|
|
template <size_t Offset, size_t Count = dynamic_extent>
|
|
constexpr span<element_type, see below> subspan() const;
|
|
|
|
constexpr span<element_type, dynamic_extent> first(size_type count) const;
|
|
constexpr span<element_type, dynamic_extent> last(size_type count) const;
|
|
constexpr span<element_type, dynamic_extent> subspan(size_type offset, size_type count = dynamic_extent) const;
|
|
|
|
// [span.obs], span observers
|
|
constexpr size_type size() const noexcept;
|
|
constexpr size_type size_bytes() const noexcept;
|
|
constexpr bool empty() const noexcept;
|
|
|
|
// [span.elem], span element access
|
|
constexpr reference operator[](size_type idx) const;
|
|
constexpr reference front() const;
|
|
constexpr reference back() const;
|
|
constexpr pointer data() const noexcept;
|
|
|
|
// [span.iterators], span iterator support
|
|
constexpr iterator begin() const noexcept;
|
|
constexpr iterator end() const noexcept;
|
|
constexpr reverse_iterator rbegin() const noexcept;
|
|
constexpr reverse_iterator rend() const noexcept;
|
|
|
|
private:
|
|
pointer data_; // exposition only
|
|
size_type size_; // exposition only
|
|
};
|
|
|
|
template<class T, size_t N>
|
|
span(T (&)[N]) -> span<T, N>;
|
|
|
|
template<class T, size_t N>
|
|
span(array<T, N>&) -> span<T, N>;
|
|
|
|
template<class T, size_t N>
|
|
span(const array<T, N>&) -> span<const T, N>;
|
|
|
|
template<class Container>
|
|
span(Container&) -> span<typename Container::value_type>;
|
|
|
|
template<class Container>
|
|
span(const Container&) -> span<const typename Container::value_type>;
|
|
|
|
} // namespace std
|
|
|
|
*/
|
|
|
|
#include <__config>
|
|
#include <__debug>
|
|
#include <__iterator/wrap_iter.h>
|
|
#include <__ranges/enable_borrowed_range.h>
|
|
#include <__ranges/enable_view.h>
|
|
#include <array> // for array
|
|
#include <cstddef> // for byte
|
|
#include <iterator> // for iterators
|
|
#include <limits>
|
|
#include <type_traits> // for remove_cv, etc
|
|
#include <version>
|
|
|
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
|
#pragma GCC system_header
|
|
#endif
|
|
|
|
_LIBCPP_PUSH_MACROS
|
|
#include <__undef_macros>
|
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
#if _LIBCPP_STD_VER > 17
|
|
|
|
inline constexpr size_t dynamic_extent = numeric_limits<size_t>::max();
|
|
template <typename _Tp, size_t _Extent = dynamic_extent> class span;
|
|
|
|
|
|
template <class _Tp>
|
|
struct __is_span_impl : public false_type {};
|
|
|
|
template <class _Tp, size_t _Extent>
|
|
struct __is_span_impl<span<_Tp, _Extent>> : public true_type {};
|
|
|
|
template <class _Tp>
|
|
struct __is_span : public __is_span_impl<remove_cv_t<_Tp>> {};
|
|
|
|
template <class _Tp>
|
|
struct __is_std_array_impl : public false_type {};
|
|
|
|
template <class _Tp, size_t _Sz>
|
|
struct __is_std_array_impl<array<_Tp, _Sz>> : public true_type {};
|
|
|
|
template <class _Tp>
|
|
struct __is_std_array : public __is_std_array_impl<remove_cv_t<_Tp>> {};
|
|
|
|
template <class _Tp, class _ElementType, class = void>
|
|
struct __is_span_compatible_container : public false_type {};
|
|
|
|
template <class _Tp, class _ElementType>
|
|
struct __is_span_compatible_container<_Tp, _ElementType,
|
|
void_t<
|
|
// is not a specialization of span
|
|
typename enable_if<!__is_span<_Tp>::value, nullptr_t>::type,
|
|
// is not a specialization of array
|
|
typename enable_if<!__is_std_array<_Tp>::value, nullptr_t>::type,
|
|
// is_array_v<Container> is false,
|
|
typename enable_if<!is_array_v<_Tp>, nullptr_t>::type,
|
|
// data(cont) and size(cont) are well formed
|
|
decltype(data(declval<_Tp>())),
|
|
decltype(size(declval<_Tp>())),
|
|
// remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[]
|
|
typename enable_if<
|
|
is_convertible_v<remove_pointer_t<decltype(data(declval<_Tp &>()))>(*)[],
|
|
_ElementType(*)[]>,
|
|
nullptr_t>::type
|
|
>>
|
|
: public true_type {};
|
|
|
|
|
|
template <typename _Tp, size_t _Extent>
|
|
class _LIBCPP_TEMPLATE_VIS span {
|
|
public:
|
|
// constants and types
|
|
using element_type = _Tp;
|
|
using value_type = remove_cv_t<_Tp>;
|
|
using size_type = size_t;
|
|
using difference_type = ptrdiff_t;
|
|
using pointer = _Tp *;
|
|
using const_pointer = const _Tp *;
|
|
using reference = _Tp &;
|
|
using const_reference = const _Tp &;
|
|
#if (_LIBCPP_DEBUG_LEVEL == 2) || defined(_LIBCPP_ABI_SPAN_POINTER_ITERATORS)
|
|
using iterator = pointer;
|
|
#else
|
|
using iterator = __wrap_iter<pointer>;
|
|
#endif
|
|
using reverse_iterator = _VSTD::reverse_iterator<iterator>;
|
|
|
|
static constexpr size_type extent = _Extent;
|
|
|
|
// [span.cons], span constructors, copy, assignment, and destructor
|
|
template <size_t _Sz = _Extent, enable_if_t<_Sz == 0, nullptr_t> = nullptr>
|
|
_LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr} {}
|
|
|
|
constexpr span (const span&) noexcept = default;
|
|
constexpr span& operator=(const span&) noexcept = default;
|
|
|
|
_LIBCPP_INLINE_VISIBILITY constexpr explicit span(pointer __ptr, size_type __count) : __data{__ptr}
|
|
{ (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); }
|
|
_LIBCPP_INLINE_VISIBILITY constexpr explicit span(pointer __f, pointer __l) : __data{__f}
|
|
{ (void)__l; _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); }
|
|
|
|
_LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent]) noexcept : __data{__arr} {}
|
|
|
|
template <class _OtherElementType,
|
|
enable_if_t<is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span(array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {}
|
|
|
|
template <class _OtherElementType,
|
|
enable_if_t<is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span(const array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {}
|
|
|
|
template <class _Container>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr explicit span( _Container& __c,
|
|
enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
|
|
: __data{_VSTD::data(__c)} {
|
|
_LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (range)");
|
|
}
|
|
|
|
template <class _Container>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr explicit span(const _Container& __c,
|
|
enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
|
|
: __data{_VSTD::data(__c)} {
|
|
_LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (range)");
|
|
}
|
|
|
|
template <class _OtherElementType>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span(const span<_OtherElementType, _Extent>& __other,
|
|
enable_if_t<
|
|
is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
|
|
nullptr_t> = nullptr)
|
|
: __data{__other.data()} {}
|
|
|
|
template <class _OtherElementType>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr explicit span(const span<_OtherElementType, dynamic_extent>& __other,
|
|
enable_if_t<
|
|
is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
|
|
nullptr_t> = nullptr) noexcept
|
|
: __data{__other.data()} { _LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); }
|
|
|
|
|
|
// ~span() noexcept = default;
|
|
|
|
template <size_t _Count>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span<element_type, _Count> first() const noexcept
|
|
{
|
|
static_assert(_Count <= _Extent, "Count out of range in span::first()");
|
|
return span<element_type, _Count>{data(), _Count};
|
|
}
|
|
|
|
template <size_t _Count>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span<element_type, _Count> last() const noexcept
|
|
{
|
|
static_assert(_Count <= _Extent, "Count out of range in span::last()");
|
|
return span<element_type, _Count>{data() + size() - _Count, _Count};
|
|
}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept
|
|
{
|
|
_LIBCPP_ASSERT(__count <= size(), "Count out of range in span::first(count)");
|
|
return {data(), __count};
|
|
}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept
|
|
{
|
|
_LIBCPP_ASSERT(__count <= size(), "Count out of range in span::last(count)");
|
|
return {data() + size() - __count, __count};
|
|
}
|
|
|
|
template <size_t _Offset, size_t _Count = dynamic_extent>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr auto subspan() const noexcept
|
|
-> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>
|
|
{
|
|
static_assert(_Offset <= _Extent, "Offset out of range in span::subspan()");
|
|
static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset, "Offset + count out of range in span::subspan()");
|
|
|
|
using _ReturnType = span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>;
|
|
return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
|
|
}
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span<element_type, dynamic_extent>
|
|
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(__count <= size() || __count == dynamic_extent, "Count out of range in span::subspan(offset, count)");
|
|
if (__count == dynamic_extent)
|
|
return {data() + __offset, size() - __offset};
|
|
_LIBCPP_ASSERT(__count <= size() - __offset, "Offset + count out of range in span::subspan(offset, count)");
|
|
return {data() + __offset, __count};
|
|
}
|
|
|
|
_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 bool empty() const noexcept { return _Extent == 0; }
|
|
|
|
_LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept
|
|
{
|
|
_LIBCPP_ASSERT(__idx < size(), "span<T,N>[] index out of bounds");
|
|
return __data[__idx];
|
|
}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept
|
|
{
|
|
_LIBCPP_ASSERT(!empty(), "span<T, N>::front() on empty span");
|
|
return __data[0];
|
|
}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept
|
|
{
|
|
_LIBCPP_ASSERT(!empty(), "span<T, N>::back() on empty span");
|
|
return __data[size()-1];
|
|
}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; }
|
|
|
|
// [span.iter], span iterator support
|
|
_LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); }
|
|
_LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); }
|
|
_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 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()}; }
|
|
|
|
_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()}; }
|
|
|
|
private:
|
|
pointer __data;
|
|
|
|
};
|
|
|
|
|
|
template <typename _Tp>
|
|
class _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> {
|
|
private:
|
|
|
|
public:
|
|
// constants and types
|
|
using element_type = _Tp;
|
|
using value_type = remove_cv_t<_Tp>;
|
|
using size_type = size_t;
|
|
using difference_type = ptrdiff_t;
|
|
using pointer = _Tp *;
|
|
using const_pointer = const _Tp *;
|
|
using reference = _Tp &;
|
|
using const_reference = const _Tp &;
|
|
#if (_LIBCPP_DEBUG_LEVEL == 2) || defined(_LIBCPP_ABI_SPAN_POINTER_ITERATORS)
|
|
using iterator = pointer;
|
|
#else
|
|
using iterator = __wrap_iter<pointer>;
|
|
#endif
|
|
using reverse_iterator = _VSTD::reverse_iterator<iterator>;
|
|
|
|
static constexpr size_type extent = dynamic_extent;
|
|
|
|
// [span.cons], span constructors, copy, assignment, and destructor
|
|
_LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} {}
|
|
|
|
constexpr span (const span&) noexcept = default;
|
|
constexpr span& operator=(const span&) noexcept = default;
|
|
|
|
_LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, size_type __count) : __data{__ptr}, __size{__count} {}
|
|
_LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{static_cast<size_t>(distance(__f, __l))} {}
|
|
|
|
template <size_t _Sz>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span(element_type (&__arr)[_Sz]) noexcept : __data{__arr}, __size{_Sz} {}
|
|
|
|
template <class _OtherElementType, size_t _Sz,
|
|
enable_if_t<is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span(array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
|
|
|
|
template <class _OtherElementType, size_t _Sz,
|
|
enable_if_t<is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
|
|
|
|
template <class _Container>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span( _Container& __c,
|
|
enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
|
|
: __data{_VSTD::data(__c)}, __size{(size_type) _VSTD::size(__c)} {}
|
|
|
|
template <class _Container>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span(const _Container& __c,
|
|
enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
|
|
: __data{_VSTD::data(__c)}, __size{(size_type) _VSTD::size(__c)} {}
|
|
|
|
|
|
template <class _OtherElementType, size_t _OtherExtent>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span(const span<_OtherElementType, _OtherExtent>& __other,
|
|
enable_if_t<
|
|
is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
|
|
nullptr_t> = nullptr) noexcept
|
|
: __data{__other.data()}, __size{__other.size()} {}
|
|
|
|
// ~span() noexcept = default;
|
|
|
|
template <size_t _Count>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span<element_type, _Count> first() const noexcept
|
|
{
|
|
_LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()");
|
|
return span<element_type, _Count>{data(), _Count};
|
|
}
|
|
|
|
template <size_t _Count>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span<element_type, _Count> last() const noexcept
|
|
{
|
|
_LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()");
|
|
return span<element_type, _Count>{data() + size() - _Count, _Count};
|
|
}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept
|
|
{
|
|
_LIBCPP_ASSERT(__count <= size(), "Count out of range in span::first(count)");
|
|
return {data(), __count};
|
|
}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span<element_type, dynamic_extent> last (size_type __count) const noexcept
|
|
{
|
|
_LIBCPP_ASSERT(__count <= size(), "Count out of range in span::last(count)");
|
|
return {data() + size() - __count, __count};
|
|
}
|
|
|
|
template <size_t _Offset, size_t _Count = dynamic_extent>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
constexpr span<element_type, _Count> subspan() const noexcept
|
|
{
|
|
_LIBCPP_ASSERT(_Offset <= size(), "Offset out of range in span::subspan()");
|
|
_LIBCPP_ASSERT(_Count == dynamic_extent || _Count <= size() - _Offset, "Offset + count out of range in span::subspan()");
|
|
return span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
|
|
}
|
|
|
|
constexpr span<element_type, dynamic_extent>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
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(__count <= size() || __count == dynamic_extent, "count out of range in span::subspan(offset, count)");
|
|
if (__count == dynamic_extent)
|
|
return {data() + __offset, size() - __offset};
|
|
_LIBCPP_ASSERT(__count <= size() - __offset, "Offset + count out of range in span::subspan(offset, count)");
|
|
return {data() + __offset, __count};
|
|
}
|
|
|
|
_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 bool empty() const noexcept { return __size == 0; }
|
|
|
|
_LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept
|
|
{
|
|
_LIBCPP_ASSERT(__idx < size(), "span<T>[] index out of bounds");
|
|
return __data[__idx];
|
|
}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept
|
|
{
|
|
_LIBCPP_ASSERT(!empty(), "span<T>[].front() on empty span");
|
|
return __data[0];
|
|
}
|
|
|
|
_LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept
|
|
{
|
|
_LIBCPP_ASSERT(!empty(), "span<T>[].back() on empty span");
|
|
return __data[size()-1];
|
|
}
|
|
|
|
|
|
_LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; }
|
|
|
|
// [span.iter], span iterator support
|
|
_LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); }
|
|
_LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); }
|
|
_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 span<const byte, dynamic_extent> __as_bytes() const noexcept
|
|
{ return {reinterpret_cast<const byte *>(data()), size_bytes()}; }
|
|
|
|
_LIBCPP_INLINE_VISIBILITY span<byte, dynamic_extent> __as_writable_bytes() const noexcept
|
|
{ return {reinterpret_cast<byte *>(data()), size_bytes()}; }
|
|
|
|
private:
|
|
pointer __data;
|
|
size_type __size;
|
|
};
|
|
|
|
#if !defined(_LIBCPP_HAS_NO_RANGES)
|
|
template <class _Tp, size_t _Extent>
|
|
inline constexpr bool ranges::enable_borrowed_range<span<_Tp, _Extent> > = true;
|
|
|
|
template <class _ElementType, size_t _Extent>
|
|
inline constexpr bool ranges::enable_view<span<_ElementType, _Extent>> = true;
|
|
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
|
|
|
|
// as_bytes & as_writable_bytes
|
|
template <class _Tp, size_t _Extent>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
auto as_bytes(span<_Tp, _Extent> __s) noexcept
|
|
-> decltype(__s.__as_bytes())
|
|
{ return __s.__as_bytes(); }
|
|
|
|
template <class _Tp, size_t _Extent>
|
|
_LIBCPP_INLINE_VISIBILITY
|
|
auto as_writable_bytes(span<_Tp, _Extent> __s) noexcept
|
|
-> enable_if_t<!is_const_v<_Tp>, decltype(__s.__as_writable_bytes())>
|
|
{ return __s.__as_writable_bytes(); }
|
|
|
|
// Deduction guides
|
|
template<class _Tp, size_t _Sz>
|
|
span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>;
|
|
|
|
template<class _Tp, size_t _Sz>
|
|
span(array<_Tp, _Sz>&) -> span<_Tp, _Sz>;
|
|
|
|
template<class _Tp, size_t _Sz>
|
|
span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>;
|
|
|
|
template<class _Container>
|
|
span(_Container&) -> span<typename _Container::value_type>;
|
|
|
|
template<class _Container>
|
|
span(const _Container&) -> span<const typename _Container::value_type>;
|
|
|
|
#endif // _LIBCPP_STD_VER > 17
|
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
_LIBCPP_POP_MACROS
|
|
|
|
#endif // _LIBCPP_SPAN
|