1 //===-- Standalone implementation std::span ---------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
8 #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_SPAN_H
9 #define LLVM_LIBC_SRC___SUPPORT_CPP_SPAN_H
11 #include <stddef.h> // For size_t
13 #include "array.h" // For array
14 #include "src/__support/macros/config.h"
15 #include "type_traits.h" // For remove_cv_t, enable_if_t, is_same_v, is_const_v
17 #include "src/__support/macros/attributes.h"
19 namespace LIBC_NAMESPACE_DECL
{
22 // A trimmed down implementation of std::span.
24 // - No constant size spans (e.g. Span<int, 4>),
25 // - Only handle pointer like types, no fancy interators nor object overriding
27 // - No implicit type conversion (e.g. Span<B>, initialized with As where A
29 // - No reverse iterators
30 template <typename T
> class span
{
32 LIBC_INLINE_VAR
static constexpr bool is_const_view_v
=
33 !cpp::is_const_v
<U
> && cpp::is_const_v
<T
> &&
34 cpp::is_same_v
<U
, remove_cv_t
<T
>>;
37 LIBC_INLINE_VAR
static constexpr bool is_compatible_v
=
38 cpp::is_same_v
<U
, T
> || is_const_view_v
<U
>;
41 using element_type
= T
;
42 using value_type
= remove_cv_t
<T
>;
43 using size_type
= size_t;
44 using difference_type
= ptrdiff_t;
46 using const_pointer
= const T
*;
47 using reference
= T
&;
48 using const_reference
= const T
&;
51 LIBC_INLINE_VAR
static constexpr size_type dynamic_extent
= -1;
53 LIBC_INLINE
constexpr span() : span_data(nullptr), span_size(0) {}
55 LIBC_INLINE
constexpr span(pointer first
, size_type count
)
56 : span_data(first
), span_size(count
) {}
58 LIBC_INLINE
constexpr span(pointer first
, pointer end
)
59 : span_data(first
), span_size(end
- first
) {}
61 template <typename U
, size_t N
,
62 cpp::enable_if_t
<is_compatible_v
<U
>, bool> = true>
63 LIBC_INLINE
constexpr span(U (&arr
)[N
]) : span_data(arr
), span_size(N
) {}
65 template <typename U
, size_t N
,
66 cpp::enable_if_t
<is_compatible_v
<U
>, bool> = true>
67 LIBC_INLINE
constexpr span(array
<U
, N
> &arr
)
68 : span_data(arr
.data()), span_size(arr
.size()) {}
70 template <typename U
, cpp::enable_if_t
<is_compatible_v
<U
>, bool> = true>
71 LIBC_INLINE
constexpr span(span
<U
> &s
)
72 : span_data(s
.data()), span_size(s
.size()) {}
74 template <typename U
, cpp::enable_if_t
<is_compatible_v
<U
>, bool> = true>
75 LIBC_INLINE
constexpr span
&operator=(span
<U
> &s
) {
81 LIBC_INLINE
~span() = default;
83 LIBC_INLINE
constexpr reference
operator[](size_type index
) const {
87 LIBC_INLINE
constexpr iterator
begin() const { return data(); }
88 LIBC_INLINE
constexpr iterator
end() const { return data() + size(); }
89 LIBC_INLINE
constexpr reference
front() const { return (*this)[0]; }
90 LIBC_INLINE
constexpr reference
back() const { return (*this)[size() - 1]; }
91 LIBC_INLINE
constexpr pointer
data() const { return span_data
; }
92 LIBC_INLINE
constexpr size_type
size() const { return span_size
; }
93 LIBC_INLINE
constexpr size_type
size_bytes() const {
94 return sizeof(T
) * size();
96 LIBC_INLINE
constexpr bool empty() const { return size() == 0; }
98 LIBC_INLINE
constexpr span
<element_type
>
99 subspan(size_type offset
, size_type count
= dynamic_extent
) const {
100 return span
<element_type
>(data() + offset
, count_to_size(offset
, count
));
103 LIBC_INLINE
constexpr span
<element_type
> first(size_type count
) const {
104 return subspan(0, count
);
107 LIBC_INLINE
constexpr span
<element_type
> last(size_type count
) const {
108 return span
<element_type
>(data() + (size() - count
), count
);
112 LIBC_INLINE
constexpr size_type
count_to_size(size_type offset
,
113 size_type count
) const {
114 if (count
== dynamic_extent
) {
115 return size() - offset
;
125 } // namespace LIBC_NAMESPACE_DECL
127 #endif // LLVM_LIBC_SRC___SUPPORT_CPP_SPAN_H