Modified: trunk/Source/WTF/wtf/Span.h (279061 => 279062)
--- trunk/Source/WTF/wtf/Span.h 2021-06-21 01:19:50 UTC (rev 279061)
+++ trunk/Source/WTF/wtf/Span.h 2021-06-21 02:51:33 UTC (rev 279062)
@@ -1,620 +1,458 @@
-// Copyright Tristan Brindle 2018.
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file ../LICENSE_1_0-Boost.txt or copy at
-// https://www.boost.org/LICENSE_1_0.txt)
+// -*- 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
+//
+//===---------------------------------------------------------------------===//
-// This is an implementation of C++20's std::span http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4820.pdf
+#ifndef _WTF_LIBCPP_SPAN
+#define _WTF_LIBCPP_SPAN
-// This has been modified from the original version to make the following changes:
-// Renamed tcb::span to WTF::Span.
-// Renamed tcb::as_bytes to WTF::asBytes.
-// Renamed tcb::as_writable_bytes to WTF::asWritableBytes.
+// Imports a copy of <span> from e892705d74c7366a1404a3b3471001edaa7659f8 of the
+// libc++ project (https://github.com/llvm/llvm-project.git) and modifies it to
+// work on top of any standard library implementation.
+//
+// - Renames macros with _LIBCPP_ prefix to use the prefix _WTF_LIBCPP_
+// - Renames std::span to WTF::Span
+// - Renames std::as_bytes/std::as_writable_bytes to WTF::asBytes/WTF::asWritableBytes.
+// - Stop #including internal libc++ headers.
+// - Remove check for > c++17.
+// - Remove push/pop availability of min/max macros.
-#ifndef TCB_SPAN_HPP_INCLUDED
-#define TCB_SPAN_HPP_INCLUDED
+#include <array> // for array
+#include <cstddef> // for byte
+#include <iterator> // for iterators
+#include <type_traits> // for remove_cv, etc
-#include <array>
-#include <cstddef>
-#include <cstdint>
-#include <type_traits>
+// Adds some macro defines usually defined in __config.
-#ifndef TCB_SPAN_NO_EXCEPTIONS
-// Attempt to discover whether we're being compiled with exception support
-#if !(defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND))
-#define TCB_SPAN_NO_EXCEPTIONS
-#endif
-#endif
+#define _WTF_LIBCPP_ABI_SPAN_POINTER_ITERATORS
+#define _WTF_LIBCPP_BEGIN_NAMESPACE namespace WTF {
+#define _WTF_LIBCPP_DEBUG_LEVEL 0
+#define _WTF_LIBCPP_END_NAMESPACE }
+#define _WTF_LIBCPP_HAS_NO_RANGES
+#define _WTF_LIBCPP_INLINE_VISIBILITY
+#define _WTF_LIBCPP_TEMPLATE_VIS
+#define _WTF_VSTD std
-#ifndef TCB_SPAN_NO_EXCEPTIONS
-#include <cstdio>
-#include <stdexcept>
-#endif
+#include <wtf/Assertions.h>
+#define _WTF_LIBCPP_ASSERT ASSERT
-// Various feature test macros
+_WTF_LIBCPP_BEGIN_NAMESPACE
-#ifndef TCB_SPAN_NAMESPACE_NAME
-#define TCB_SPAN_NAMESPACE_NAME WTF
-#endif
+inline constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
+template <typename _Tp, std::size_t _Extent = dynamic_extent> class Span;
-#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
-#define TCB_SPAN_HAVE_CPP17
-#endif
-#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
-#define TCB_SPAN_HAVE_CPP14
-#endif
+template <class _Tp>
+struct __is_span_impl : public std::false_type {};
-namespace TCB_SPAN_NAMESPACE_NAME {
+template <class _Tp, std::size_t _Extent>
+struct __is_span_impl<Span<_Tp, _Extent>> : public std::true_type {};
-// Establish default contract checking behavior
-#if !defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION) && \
- !defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION) && \
- !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
-#if defined(NDEBUG) || !defined(TCB_SPAN_HAVE_CPP14)
-#define TCB_SPAN_NO_CONTRACT_CHECKING
-#else
-#define TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION
-#endif
-#endif
+template <class _Tp>
+struct __is_span : public __is_span_impl<std::remove_cv_t<_Tp>> {};
-#if defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION)
-struct contract_violation_error : std::logic_error {
- explicit contract_violation_error(const char* msg) : std::logic_error(msg)
- {}
-};
+template <class _Tp>
+struct __is_std_array_impl : public std::false_type {};
-inline void contract_violation(const char* msg)
-{
- throw contract_violation_error(msg);
-}
+template <class _Tp, std::size_t _Sz>
+struct __is_std_array_impl<std::array<_Tp, _Sz>> : public std::true_type {};
-#elif defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION)
-[[noreturn]] inline void contract_violation(const char* /*unused*/)
-{
- std::terminate();
-}
-#endif
+template <class _Tp>
+struct __is_std_array : public __is_std_array_impl<std::remove_cv_t<_Tp>> {};
-#if !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
-#define TCB_SPAN_STRINGIFY(cond) #cond
-#define TCB_SPAN_EXPECT(cond) \
- cond ? (void) 0 : contract_violation("Expected " TCB_SPAN_STRINGIFY(cond))
-#else
-#define TCB_SPAN_EXPECT(cond)
-#endif
+template <class _Tp, class _ElementType, class = void>
+struct __is_span_compatible_container : public std::false_type {};
-#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_inline_variables)
-#define TCB_SPAN_INLINE_VAR inline
-#else
-#define TCB_SPAN_INLINE_VAR
-#endif
+template <class _Tp, class _ElementType>
+struct __is_span_compatible_container<_Tp, _ElementType,
+ std::void_t<
+ // is not a specialization of Span
+ typename std::enable_if<!__is_span<_Tp>::value, nullptr_t>::type,
+ // is not a specialization of array
+ typename std::enable_if<!__is_std_array<_Tp>::value, nullptr_t>::type,
+ // sd::is_array_v<Container> is false,
+ typename std::enable_if<!std::is_array_v<_Tp>, nullptr_t>::type,
+ // std::data(cont) and std::size(cont) are well formed
+ decltype(std::data(std::declval<_Tp>())),
+ decltype(std::size(std::declval<_Tp>())),
+ // remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[]
+ typename std::enable_if<
+ std::is_convertible_v<std::remove_pointer_t<decltype(std::data(std::declval<_Tp &>()))>(*)[],
+ _ElementType(*)[]>,
+ nullptr_t>::type
+ >>
+ : public std::true_type {};
-#if defined(TCB_SPAN_HAVE_CPP14) || \
- (defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
-#define TCB_SPAN_HAVE_CPP14_CONSTEXPR
-#endif
-#if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR)
-#define TCB_SPAN_CONSTEXPR14 constexpr
+template <typename _Tp, std::size_t _Extent>
+class _WTF_LIBCPP_TEMPLATE_VIS Span {
+public:
+// constants and types
+ using element_type = _Tp;
+ using value_type = std::remove_cv_t<_Tp>;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+ using pointer = _Tp *;
+ using const_pointer = const _Tp *;
+ using reference = _Tp &;
+ using const_reference = const _Tp &;
+#if (_WTF_LIBCPP_DEBUG_LEVEL == 2) || defined(_WTF_LIBCPP_ABI_SPAN_POINTER_ITERATORS)
+ using iterator = pointer;
#else
-#define TCB_SPAN_CONSTEXPR14
+ using iterator = __wrap_iter<pointer>;
#endif
+ using reverse_iterator = _WTF_VSTD::reverse_iterator<iterator>;
-#if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR) && \
- (!defined(_MSC_VER) || _MSC_VER > 1900)
-#define TCB_SPAN_CONSTEXPR_ASSIGN constexpr
-#else
-#define TCB_SPAN_CONSTEXPR_ASSIGN
-#endif
+ static constexpr size_type extent = _Extent;
-#if defined(TCB_SPAN_NO_CONTRACT_CHECKING)
-#define TCB_SPAN_CONSTEXPR11 constexpr
-#else
-#define TCB_SPAN_CONSTEXPR11 TCB_SPAN_CONSTEXPR14
-#endif
+// [span.cons], span constructors, copy, assignment, and destructor
+ template <std::size_t _Sz = _Extent, std::enable_if_t<_Sz == 0, nullptr_t> = nullptr>
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr Span() noexcept : __data{nullptr} {}
-#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_deduction_guides)
-#define TCB_SPAN_HAVE_DEDUCTION_GUIDES
-#endif
+ constexpr Span (const Span&) noexcept = default;
+ constexpr Span& operator=(const Span&) noexcept = default;
-#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_byte)
-#define TCB_SPAN_HAVE_STD_BYTE
-#endif
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr explicit Span(pointer __ptr, size_type __count) : __data{__ptr}
+ { (void)__count; _WTF_LIBCPP_ASSERT(_Extent == __count, "size mismatch in Span's constructor (ptr, len)"); }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr explicit Span(pointer __f, pointer __l) : __data{__f}
+ { (void)__l; _WTF_LIBCPP_ASSERT(_Extent == std::distance(__f, __l), "size mismatch in Span's constructor (ptr, ptr)"); }
-#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_array_constexpr)
-#define TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC
-#endif
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr Span(element_type (&__arr)[_Extent]) noexcept : __data{__arr} {}
-#if defined(TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC)
-#define TCB_SPAN_ARRAY_CONSTEXPR constexpr
-#else
-#define TCB_SPAN_ARRAY_CONSTEXPR
-#endif
+ template <class _OtherElementType,
+ std::enable_if_t<std::is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span(std::array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {}
-#ifdef TCB_SPAN_HAVE_STD_BYTE
-using byte = std::byte;
-#else
-using byte = unsigned char;
-#endif
+ template <class _OtherElementType,
+ std::enable_if_t<std::is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span(const std::array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {}
-#if defined(TCB_SPAN_HAVE_CPP17)
-#define TCB_SPAN_NODISCARD [[nodiscard]]
-#else
-#define TCB_SPAN_NODISCARD
-#endif
+ template <class _Container>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr explicit Span( _Container& __c,
+ std::enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
+ : __data{_WTF_VSTD::data(__c)} {
+ _WTF_LIBCPP_ASSERT(_Extent == _WTF_VSTD::size(__c), "size mismatch in Span's constructor (range)");
+ }
-TCB_SPAN_INLINE_VAR constexpr std::size_t dynamic_extent = SIZE_MAX;
+ template <class _Container>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr explicit Span(const _Container& __c,
+ std::enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
+ : __data{_WTF_VSTD::data(__c)} {
+ _WTF_LIBCPP_ASSERT(_Extent == _WTF_VSTD::size(__c), "size mismatch in Span's constructor (range)");
+ }
-template <typename ElementType, std::size_t Extent = dynamic_extent>
-class Span;
+ template <class _OtherElementType>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span(const Span<_OtherElementType, _Extent>& __other,
+ std::enable_if_t<
+ std::is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
+ nullptr_t> = nullptr)
+ : __data{__other.data()} {}
-namespace detail {
+ template <class _OtherElementType>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr explicit Span(const Span<_OtherElementType>& __other,
+ std::enable_if_t<
+ std::is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
+ nullptr_t> = nullptr) noexcept
+ : __data{__other.data()} { _WTF_LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in Span's constructor (other Span)"); }
-template <typename E, std::size_t S>
-struct span_storage {
- constexpr span_storage() noexcept = default;
- constexpr span_storage(E* p_ptr, std::size_t /*unused*/) noexcept
- : ptr(p_ptr)
- {}
+// ~Span() noexcept = default;
- E* ptr = nullptr;
- static constexpr std::size_t size = S;
-};
+ template <std::size_t _Count>
+ _WTF_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 <typename E>
-struct span_storage<E, dynamic_extent> {
- constexpr span_storage() noexcept = default;
+ template <std::size_t _Count>
+ _WTF_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};
+ }
- constexpr span_storage(E* p_ptr, std::size_t p_size) noexcept
- : ptr(p_ptr), size(p_size)
- {}
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span<element_type, dynamic_extent> first(size_type __count) const noexcept
+ {
+ _WTF_LIBCPP_ASSERT(__count <= size(), "Count out of range in Span::first(count)");
+ return {data(), __count};
+ }
- E* ptr = nullptr;
- std::size_t size = 0;
-};
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span<element_type, dynamic_extent> last(size_type __count) const noexcept
+ {
+ _WTF_LIBCPP_ASSERT(__count <= size(), "Count out of range in Span::last(count)");
+ return {data() + size() - __count, __count};
+ }
-// Reimplementation of C++17 std::size() and std::data()
-#if defined(TCB_SPAN_HAVE_CPP17) || \
- defined(__cpp_lib_nonmember_container_access)
-using std::data;
-using std::size;
-#else
-template <class C>
-constexpr auto size(const C& c) -> decltype(c.size())
-{
- return c.size();
-}
+ template <std::size_t _Offset, std::size_t _Count = dynamic_extent>
+ _WTF_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()");
-template <class T, std::size_t N>
-constexpr std::size_t size(const T (&)[N]) noexcept
-{
- return N;
-}
+ using _ReturnType = Span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>;
+ return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
+ }
-template <class C>
-constexpr auto data(C& c) -> decltype(c.data())
-{
- return c.data();
-}
-template <class C>
-constexpr auto data(const C& c) -> decltype(c.data())
-{
- return c.data();
-}
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span<element_type, dynamic_extent>
+ subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept
+ {
+ _WTF_LIBCPP_ASSERT(__offset <= size(), "Offset out of range in Span::subspan(offset, count)");
+ _WTF_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};
+ _WTF_LIBCPP_ASSERT(__count <= size() - __offset, "Offset + count out of range in Span::subspan(offset, count)");
+ return {data() + __offset, __count};
+ }
-template <class T, std::size_t N>
-constexpr T* data(T (&array)[N]) noexcept
-{
- return array;
-}
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr size_type size() const noexcept { return _Extent; }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr size_type size_bytes() const noexcept { return _Extent * sizeof(element_type); }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return _Extent == 0; }
-template <class E>
-constexpr const E* data(std::initializer_list<E> il) noexcept
-{
- return il.begin();
-}
-#endif // TCB_SPAN_HAVE_CPP17
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept
+ {
+ _WTF_LIBCPP_ASSERT(__idx < size(), "Span<T,N>[] index out of bounds");
+ return __data[__idx];
+ }
-#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_void_t)
-using std::void_t;
-#else
-template <typename...>
-using void_t = void;
-#endif
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept
+ {
+ _WTF_LIBCPP_ASSERT(!empty(), "Span<T, N>::front() on empty Span");
+ return __data[0];
+ }
-template <typename T>
-using uncvref_t =
- typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept
+ {
+ _WTF_LIBCPP_ASSERT(!empty(), "Span<T, N>::back() on empty Span");
+ return __data[size()-1];
+ }
-template <typename>
-struct is_span : std::false_type {};
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; }
-template <typename T, std::size_t S>
-struct is_span<Span<T, S>> : std::true_type {};
+// [span.iter], Span iterator support
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
-template <typename>
-struct is_std_array : std::false_type {};
+private:
+ pointer __data;
-template <typename T, std::size_t N>
-struct is_std_array<std::array<T, N>> : std::true_type {};
-
-template <typename, typename = void>
-struct has_size_and_data : std::false_type {};
-
-template <typename T>
-struct has_size_and_data<T, void_t<decltype(detail::size(std::declval<T>())),
- decltype(detail::data(std::declval<T>()))>>
- : std::true_type {};
-
-template <typename C, typename U = uncvref_t<C>>
-struct is_container {
- static constexpr bool value =
- !is_span<U>::value && !is_std_array<U>::value &&
- !std::is_array<U>::value && has_size_and_data<C>::value;
};
-template <typename T>
-using remove_pointer_t = typename std::remove_pointer<T>::type;
-template <typename, typename, typename = void>
-struct is_container_element_type_compatible : std::false_type {};
+template <typename _Tp>
+class _WTF_LIBCPP_TEMPLATE_VIS Span<_Tp, dynamic_extent> {
+private:
-template <typename T, typename E>
-struct is_container_element_type_compatible<
- T, E,
- typename std::enable_if<
- !std::is_same<typename std::remove_cv<decltype(
- detail::data(std::declval<T>()))>::type,
- void>::value>::type>
- : std::is_convertible<
- remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
- E (*)[]> {};
-
-template <typename, typename = size_t>
-struct is_complete : std::false_type {};
-
-template <typename T>
-struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
-
-} // namespace detail
-
-template <typename ElementType, std::size_t Extent>
-class Span {
- static_assert(std::is_object<ElementType>::value,
- "A Span's ElementType must be an object type (not a "
- "reference type or void)");
- static_assert(detail::is_complete<ElementType>::value,
- "A Span's ElementType must be a complete type (not a forward "
- "declaration)");
- static_assert(!std::is_abstract<ElementType>::value,
- "A Span's ElementType cannot be an abstract class type");
-
- using storage_type = detail::span_storage<ElementType, Extent>;
-
public:
- // constants and types
- using element_type = ElementType;
- using value_type = typename std::remove_cv<ElementType>::type;
- using size_type = std::size_t;
- using difference_type = std::ptrdiff_t;
- using pointer = element_type*;
- using const_pointer = const element_type*;
- using reference = element_type&;
- using const_reference = const element_type&;
- using iterator = pointer;
- using reverse_iterator = std::reverse_iterator<iterator>;
+// constants and types
+ using element_type = _Tp;
+ using value_type = std::remove_cv_t<_Tp>;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+ using pointer = _Tp *;
+ using const_pointer = const _Tp *;
+ using reference = _Tp &;
+ using const_reference = const _Tp &;
+#if (_WTF_LIBCPP_DEBUG_LEVEL == 2) || defined(_WTF_LIBCPP_ABI_SPAN_POINTER_ITERATORS)
+ using iterator = pointer;
+#else
+ using iterator = __wrap_iter<pointer>;
+#endif
+ using reverse_iterator = _WTF_VSTD::reverse_iterator<iterator>;
- static constexpr size_type extent = Extent;
+ static constexpr size_type extent = dynamic_extent;
- // [span.cons], Span constructors, copy, assignment, and destructor
- template <
- std::size_t E = Extent,
- typename std::enable_if<(E == dynamic_extent || E <= 0), int>::type = 0>
- constexpr Span() noexcept
- {}
+// [span.cons], Span constructors, copy, assignment, and destructor
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr Span() noexcept : __data{nullptr}, __size{0} {}
- TCB_SPAN_CONSTEXPR11 Span(pointer ptr, size_type count)
- : storage_(ptr, count)
- {
- TCB_SPAN_EXPECT(extent == dynamic_extent || count == extent);
- }
+ constexpr Span (const Span&) noexcept = default;
+ constexpr Span& operator=(const Span&) noexcept = default;
- TCB_SPAN_CONSTEXPR11 Span(pointer first_elem, pointer last_elem)
- : storage_(first_elem, last_elem - first_elem)
- {
- TCB_SPAN_EXPECT(extent == dynamic_extent ||
- last_elem - first_elem ==
- static_cast<std::ptrdiff_t>(extent));
- }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr Span(pointer __ptr, size_type __count) : __data{__ptr}, __size{__count} {}
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr Span(pointer __f, pointer __l) : __data{__f}, __size{static_cast<std::size_t>(std::distance(__f, __l))} {}
- template <std::size_t N, std::size_t E = Extent,
- typename std::enable_if<
- (E == dynamic_extent || N == E) &&
- detail::is_container_element_type_compatible<
- element_type (&)[N], ElementType>::value,
- int>::type = 0>
- constexpr Span(element_type (&arr)[N]) noexcept : storage_(arr, N)
- {}
+ template <std::size_t _Sz>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span(element_type (&__arr)[_Sz]) noexcept : __data{__arr}, __size{_Sz} {}
- template <std::size_t N, std::size_t E = Extent,
- typename std::enable_if<
- (E == dynamic_extent || N == E) &&
- detail::is_container_element_type_compatible<
- std::array<value_type, N>&, ElementType>::value,
- int>::type = 0>
- TCB_SPAN_ARRAY_CONSTEXPR Span(std::array<value_type, N>& arr) noexcept
- : storage_(arr.data(), N)
- {}
+ template <class _OtherElementType, std::size_t _Sz,
+ std::enable_if_t<std::is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span(std::array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
- template <std::size_t N, std::size_t E = Extent,
- typename std::enable_if<
- (E == dynamic_extent || N == E) &&
- detail::is_container_element_type_compatible<
- const std::array<value_type, N>&, ElementType>::value,
- int>::type = 0>
- TCB_SPAN_ARRAY_CONSTEXPR Span(const std::array<value_type, N>& arr) noexcept
- : storage_(arr.data(), N)
- {}
+ template <class _OtherElementType, std::size_t _Sz,
+ std::enable_if_t<std::is_convertible_v<const _OtherElementType(*)[], element_type (*)[]>, nullptr_t> = nullptr>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span(const std::array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
- template <
- typename Container, std::size_t E = Extent,
- typename std::enable_if<
- E == dynamic_extent && detail::is_container<Container>::value &&
- detail::is_container_element_type_compatible<
- Container&, ElementType>::value,
- int>::type = 0>
- constexpr Span(Container& cont)
- : storage_(detail::data(cont), detail::size(cont))
- {}
+ template <class _Container>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span( _Container& __c,
+ std::enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
+ : __data{_WTF_VSTD::data(__c)}, __size{(size_type) _WTF_VSTD::size(__c)} {}
- template <
- typename Container, std::size_t E = Extent,
- typename std::enable_if<
- E == dynamic_extent && detail::is_container<Container>::value &&
- detail::is_container_element_type_compatible<
- const Container&, ElementType>::value,
- int>::type = 0>
- constexpr Span(const Container& cont)
- : storage_(detail::data(cont), detail::size(cont))
- {}
+ template <class _Container>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span(const _Container& __c,
+ std::enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
+ : __data{_WTF_VSTD::data(__c)}, __size{(size_type) _WTF_VSTD::size(__c)} {}
- constexpr Span(const Span& other) noexcept = default;
- template <typename OtherElementType, std::size_t OtherExtent,
- typename std::enable_if<
- (Extent == OtherExtent || Extent == dynamic_extent) &&
- std::is_convertible<OtherElementType (*)[],
- ElementType (*)[]>::value,
- int>::type = 0>
- constexpr Span(const Span<OtherElementType, OtherExtent>& other) noexcept
- : storage_(other.data(), other.size())
- {}
+ template <class _OtherElementType, std::size_t _OtherExtent>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span(const Span<_OtherElementType, _OtherExtent>& __other,
+ std::enable_if_t<
+ std::is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
+ nullptr_t> = nullptr) noexcept
+ : __data{__other.data()}, __size{__other.size()} {}
- ~Span() noexcept = default;
+// ~Span() noexcept = default;
- TCB_SPAN_CONSTEXPR_ASSIGN Span&
- operator=(const Span& other) noexcept = default;
-
- // [span.sub], span subviews
- template <std::size_t Count>
- TCB_SPAN_CONSTEXPR11 Span<element_type, Count> first() const
+ template <std::size_t _Count>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span<element_type, _Count> first() const noexcept
{
- TCB_SPAN_EXPECT(Count <= size());
- return {data(), Count};
+ _WTF_LIBCPP_ASSERT(_Count <= size(), "Count out of range in Span::first()");
+ return Span<element_type, _Count>{data(), _Count};
}
- template <std::size_t Count>
- TCB_SPAN_CONSTEXPR11 Span<element_type, Count> last() const
+ template <std::size_t _Count>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span<element_type, _Count> last() const noexcept
{
- TCB_SPAN_EXPECT(Count <= size());
- return {data() + (size() - Count), Count};
+ _WTF_LIBCPP_ASSERT(_Count <= size(), "Count out of range in Span::last()");
+ return Span<element_type, _Count>{data() + size() - _Count, _Count};
}
- template <std::size_t Offset, std::size_t Count = dynamic_extent>
- using subspan_return_t =
- Span<ElementType, Count != dynamic_extent
- ? Count
- : (Extent != dynamic_extent ? Extent - Offset
- : dynamic_extent)>;
-
- template <std::size_t Offset, std::size_t Count = dynamic_extent>
- TCB_SPAN_CONSTEXPR11 subspan_return_t<Offset, Count> subspan() const
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span<element_type, dynamic_extent> first(size_type __count) const noexcept
{
- TCB_SPAN_EXPECT(Offset <= size() &&
- (Count == dynamic_extent || Offset + Count <= size()));
- return {data() + Offset,
- Count != dynamic_extent ? Count : size() - Offset};
+ _WTF_LIBCPP_ASSERT(__count <= size(), "Count out of range in Span::first(count)");
+ return {data(), __count};
}
- TCB_SPAN_CONSTEXPR11 Span<element_type, dynamic_extent>
- first(size_type count) const
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span<element_type, dynamic_extent> last (size_type __count) const noexcept
{
- TCB_SPAN_EXPECT(count <= size());
- return {data(), count};
+ _WTF_LIBCPP_ASSERT(__count <= size(), "Count out of range in Span::last(count)");
+ return {data() + size() - __count, __count};
}
- TCB_SPAN_CONSTEXPR11 Span<element_type, dynamic_extent>
- last(size_type count) const
+ template <std::size_t _Offset, std::size_t _Count = dynamic_extent>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ constexpr Span<element_type, _Count> subspan() const noexcept
{
- TCB_SPAN_EXPECT(count <= size());
- return {data() + (size() - count), count};
+ _WTF_LIBCPP_ASSERT(_Offset <= size(), "Offset out of range in Span::subspan()");
+ _WTF_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};
}
- TCB_SPAN_CONSTEXPR11 Span<element_type, dynamic_extent>
- subspan(size_type offset, size_type count = dynamic_extent) const
+ constexpr Span<element_type, dynamic_extent>
+ _WTF_LIBCPP_INLINE_VISIBILITY
+ subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept
{
- TCB_SPAN_EXPECT(offset <= size() &&
- (count == dynamic_extent || offset + count <= size()));
- return {data() + offset,
- count == dynamic_extent ? size() - offset : count};
+ _WTF_LIBCPP_ASSERT(__offset <= size(), "Offset out of range in Span::subspan(offset, count)");
+ _WTF_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};
+ _WTF_LIBCPP_ASSERT(__count <= size() - __offset, "Offset + count out of range in Span::subspan(offset, count)");
+ return {data() + __offset, __count};
}
- // [span.obs], span observers
- constexpr size_type size() const noexcept { return storage_.size; }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr size_type size() const noexcept { return __size; }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr size_type size_bytes() const noexcept { return __size * sizeof(element_type); }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return __size == 0; }
- constexpr size_type size_bytes() const noexcept
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr reference operator[](size_type __idx) const noexcept
{
- return size() * sizeof(element_type);
+ _WTF_LIBCPP_ASSERT(__idx < size(), "Span<T>[] index out of bounds");
+ return __data[__idx];
}
- TCB_SPAN_NODISCARD constexpr bool empty() const noexcept
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept
{
- return size() == 0;
+ _WTF_LIBCPP_ASSERT(!empty(), "Span<T>[].front() on empty Span");
+ return __data[0];
}
- // [span.elem], span element access
- TCB_SPAN_CONSTEXPR11 reference operator[](size_type idx) const
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept
{
- TCB_SPAN_EXPECT(idx < size());
- return *(data() + idx);
+ _WTF_LIBCPP_ASSERT(!empty(), "Span<T>[].back() on empty Span");
+ return __data[size()-1];
}
- TCB_SPAN_CONSTEXPR11 reference front() const
- {
- TCB_SPAN_EXPECT(!empty());
- return *data();
- }
- TCB_SPAN_CONSTEXPR11 reference back() const
- {
- TCB_SPAN_EXPECT(!empty());
- return *(data() + (size() - 1));
- }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; }
- constexpr pointer data() const noexcept { return storage_.ptr; }
+// [span.iter], Span iterator support
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
+ _WTF_LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
- // [span.iterators], span iterator support
- constexpr iterator begin() const noexcept { return data(); }
-
- constexpr iterator end() const noexcept { return data() + size(); }
-
- TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rbegin() const noexcept
- {
- return reverse_iterator(end());
- }
-
- TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rend() const noexcept
- {
- return reverse_iterator(begin());
- }
-
private:
- storage_type storage_{};
+ pointer __data;
+ size_type __size;
};
-#ifdef TCB_SPAN_HAVE_DEDUCTION_GUIDES
+#if !defined(_WTF_LIBCPP_HAS_NO_RANGES)
+template <class _Tp, std::size_t _Extent>
+inline constexpr bool std::ranges::enable_borrowed_range<Span<_Tp, _Extent> > = true;
+#endif // !defined(_WTF_LIBCPP_HAS_NO_RANGES)
-/* Deduction Guides */
-template <class T, size_t N>
-Span(T (&)[N])->Span<T, N>;
+// asBytes & asWritableBytes
+template <class _Tp, std::size_t _Extent>
+_WTF_LIBCPP_INLINE_VISIBILITY
+auto asBytes(Span<_Tp, _Extent> __s) noexcept
+-> Span<const std::byte, _Extent == dynamic_extent ? dynamic_extent : _Extent * sizeof(_Tp)>
+{ return { reinterpret_cast<const std::byte *>(__s.data()), __s.size_bytes() }; }
-template <class T, size_t N>
-Span(std::array<T, N>&)->Span<T, N>;
+template <class _Tp, std::size_t _Extent>
+_WTF_LIBCPP_INLINE_VISIBILITY
+auto asWritableBytes(Span<_Tp, _Extent> __s) noexcept
+-> std::enable_if_t<!std::is_const_v<_Tp>, Span<std::byte, _Extent == dynamic_extent ? dynamic_extent : _Extent * sizeof(_Tp)>>
+{ return { reinterpret_cast<std::byte *>(__s.data()), __s.size_bytes() }; }
-template <class T, size_t N>
-Span(const std::array<T, N>&)->Span<const T, N>;
+// Deduction guides
+template<class _Tp, std::size_t _Sz>
+ Span(_Tp (&)[_Sz]) -> Span<_Tp, _Sz>;
-template <class Container>
-Span(Container&)->Span<typename Container::value_type>;
+template<class _Tp, std::size_t _Sz>
+ Span(std::array<_Tp, _Sz>&) -> Span<_Tp, _Sz>;
-template <class Container>
-Span(const Container&)->Span<const typename Container::value_type>;
+template<class _Tp, std::size_t _Sz>
+ Span(const std::array<_Tp, _Sz>&) -> Span<const _Tp, _Sz>;
-#endif // TCB_SPAN_HAVE_DEDUCTION_GUIDES
+template<class _Container>
+ Span(_Container&) -> Span<typename _Container::value_type>;
-#ifdef TCB_SPAN_INCLUDE_MAKE_SPAN
+template<class _Container>
+ Span(const _Container&) -> Span<const typename _Container::value_type>;
-template <typename ElementType, std::size_t Extent>
-constexpr Span<ElementType, Extent>
-make_span(Span<ElementType, Extent> s) noexcept
-{
- return s;
-}
+_WTF_LIBCPP_END_NAMESPACE
-template <typename T, std::size_t N>
-constexpr Span<T, N> make_span(T (&arr)[N]) noexcept
-{
- return {arr};
-}
-
-template <typename T, std::size_t N>
-TCB_SPAN_ARRAY_CONSTEXPR Span<T, N> make_span(std::array<T, N>& arr) noexcept
-{
- return {arr};
-}
-
-template <typename T, std::size_t N>
-TCB_SPAN_ARRAY_CONSTEXPR Span<const T, N>
-make_span(const std::array<T, N>& arr) noexcept
-{
- return {arr};
-}
-
-template <typename Container>
-constexpr Span<typename Container::value_type> make_span(Container& cont)
-{
- return {cont};
-}
-
-template <typename Container>
-constexpr Span<const typename Container::value_type>
-make_span(const Container& cont)
-{
- return {cont};
-}
-#endif // TCB_SPAN_INCLUDE_MAKE_SPAN
-
-template <typename ElementType, std::size_t Extent>
-Span<const byte, ((Extent == dynamic_extent) ? dynamic_extent
- : sizeof(ElementType) * Extent)>
-asBytes(Span<ElementType, Extent> s) noexcept
-{
- return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
-}
-
-template <
- class ElementType, size_t Extent,
- typename std::enable_if<!std::is_const<ElementType>::value, int>::type = 0>
-Span<byte, ((Extent == dynamic_extent) ? dynamic_extent
- : sizeof(ElementType) * Extent)>
-asWritableBytes(Span<ElementType, Extent> s) noexcept
-{
- return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
-}
-
-template <std::size_t N, typename E, std::size_t S>
-constexpr auto get(Span<E, S> s) -> decltype(s[N])
-{
- return s[N];
-}
-
-} // namespace TCB_SPAN_NAMESPACE_NAME
-
-namespace std {
-
-template <typename ElementType, size_t Extent>
-class tuple_size<TCB_SPAN_NAMESPACE_NAME::Span<ElementType, Extent>>
- : public integral_constant<size_t, Extent> {};
-
-template <typename ElementType>
-class tuple_size<TCB_SPAN_NAMESPACE_NAME::Span<
- ElementType, TCB_SPAN_NAMESPACE_NAME::dynamic_extent>>; // not defined
-
-template <size_t I, typename ElementType, size_t Extent>
-class tuple_element<I, TCB_SPAN_NAMESPACE_NAME::Span<ElementType, Extent>> {
-public:
- static_assert(Extent != TCB_SPAN_NAMESPACE_NAME::dynamic_extent &&
- I < Extent,
- "");
- using type = ElementType;
-};
-
-} // end namespace std
-
using WTF::Span;
using WTF::asBytes;
using WTF::asWritableBytes;
-#endif // TCB_SPAN_HPP_INCLUDED
+#endif // _WTF_LIBCPP_SPAN