1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
//===-- Standalone implementation std::span ---------------------*- C++ -*-===//
//
// 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 LLVM_LIBC_SRC_SUPPORT_CPP_SPAN_H
#define LLVM_LIBC_SRC_SUPPORT_CPP_SPAN_H
#include <stddef.h> // For size_t
#include "array.h" // For array
#include "type_traits.h" // For remove_cv_t, enable_if_t, is_same_v, is_const_v
namespace __llvm_libc::cpp {
// A trimmed down implementation of std::span.
// Missing features:
// - No constant size spans (e.g. Span<int, 4>),
// - Only handle pointer like types, no fancy interators nor object overriding
// the & operator,
// - No implicit type conversion (e.g. Span<B>, initialized with As where A
// inherits from B),
// - No reverse iterators
template <typename T> class span {
template <typename U>
inline static constexpr bool is_const_view_v =
!cpp::is_const_v<U> && cpp::is_const_v<T> &&
cpp::is_same_v<U, remove_cv_t<T>>;
template <typename U>
inline static constexpr bool is_compatible_v =
cpp::is_same_v<U, T> || is_const_view_v<U>;
public:
using element_type = T;
using value_type = remove_cv_t<T>;
using size_type = size_t;
using difference_type = ptrdiff_t;
using pointer = T *;
using const_pointer = const T *;
using reference = T &;
using const_reference = const T &;
using iterator = T *;
static constexpr size_type dynamic_extent = -1;
constexpr span() : span_data(nullptr), span_size(0) {}
constexpr span(pointer first, size_type count)
: span_data(first), span_size(count) {}
constexpr span(pointer first, pointer end)
: span_data(first), span_size(end - first) {}
template <typename U, size_t N,
cpp::enable_if_t<is_compatible_v<U>, bool> = true>
constexpr span(U (&arr)[N]) : span_data(arr), span_size(N) {}
template <typename U, size_t N,
cpp::enable_if_t<is_compatible_v<U>, bool> = true>
constexpr span(array<U, N> &arr)
: span_data(arr.data()), span_size(arr.size()) {}
template <typename U, cpp::enable_if_t<is_compatible_v<U>, bool> = true>
constexpr span(span<U> &s) : span_data(s.data()), span_size(s.size()) {}
template <typename U, cpp::enable_if_t<is_compatible_v<U>, bool> = true>
constexpr span &operator=(span<U> &s) {
span_data = s.data();
span_size = s.size();
return *this;
}
~span() = default;
constexpr reference operator[](size_type index) const {
return data()[index];
}
constexpr iterator begin() const { return data(); }
constexpr iterator end() const { return data() + size(); }
constexpr reference front() const { return (*this)[0]; }
constexpr reference back() const { return (*this)[size() - 1]; }
constexpr pointer data() const { return span_data; }
constexpr size_type size() const { return span_size; }
constexpr size_type size_bytes() const { return sizeof(T) * size(); }
constexpr bool empty() const { return size() == 0; }
constexpr span<element_type> subspan(size_type offset,
size_type count = dynamic_extent) const {
return span<element_type>(data() + offset, count_to_size(offset, count));
}
constexpr span<element_type> first(size_type count) const {
return subspan(0, count);
}
constexpr span<element_type> last(size_type count) const {
return span<element_type>(data() + (size() - count), count);
}
private:
constexpr size_type count_to_size(size_type offset, size_type count) const {
if (count == dynamic_extent) {
return size() - offset;
}
return count;
}
T *span_data;
size_t span_size;
};
} // namespace __llvm_libc::cpp
#endif /* LLVM_LIBC_SRC_SUPPORT_CPP_SPAN_H */
|