tetl 0.1.0
Embedded Template Library
Loading...
Searching...
No Matches
span.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSL-1.0
2
3#ifndef TETL_SPAN_SPAN_HPP
4#define TETL_SPAN_SPAN_HPP
5
6#include <etl/_config/all.hpp>
7
11#include <etl/_cstddef/byte.hpp>
14#include <etl/_iterator/end.hpp>
25#include <etl/_ranges/size.hpp>
37
38namespace etl {
39
54template <typename T, size_t Extent = etl::dynamic_extent>
55struct span;
56
57namespace detail {
58
59template <typename T>
60inline constexpr auto is_span = false;
61
62template <typename T, size_t Size>
63inline constexpr auto is_span<etl::span<T, Size>> = true;
64
65template <typename From, typename To>
66concept span_convertible_from = is_convertible_v<From (*)[], To (*)[]>;
67
68template <size_t Offset, size_t Count, size_t Extent>
69[[nodiscard]] consteval auto subspan_extent() -> size_t
70{
71 if (Count != dynamic_extent) {
72 return Count;
73 }
74 if (Extent != dynamic_extent) {
75 return Extent - Offset;
76 }
77 return dynamic_extent;
78}
79
80} // namespace detail
81
82template <typename T, size_t Extent>
83struct span {
84 using element_type = T;
88 using pointer = T*;
89 using const_pointer = T const*;
90 using reference = T&;
91 using const_reference = T const&;
92 using iterator = T*;
94
97 static constexpr size_type extent = Extent;
98
104 constexpr span() noexcept
105 requires(extent == 0 or extent == dynamic_extent)
106 = default;
107
110 template <typename /*contiguous_iterator*/ It>
111 requires detail::span_convertible_from<remove_reference_t<iter_reference_t<It>>, T>
113 : _storage{first, count}
114 {
115 }
116
118 template <size_t N>
119 requires(extent == dynamic_extent or extent == N)
120 constexpr span(c_array<type_identity_t<T>, N>& arr) noexcept
121 : _storage{&arr[0], N}
122 {
123 }
124
126 template <detail::span_convertible_from<T> U, size_t N>
127 requires(extent == dynamic_extent or extent == N)
128 constexpr span(array<U, N>& arr) noexcept
129 : _storage{arr.data(), arr.size()}
130 {
131 }
132
134 template <detail::span_convertible_from<T> U, size_t N>
135 requires(extent == dynamic_extent or extent == N)
136 constexpr span(array<U, N> const& arr) noexcept
137 : _storage{arr.data(), arr.size()}
138 {
139 }
140
142 template <typename /*etl::ranges::contiguous_range*/ R>
143 // clang-format off
144 requires (
145 ranges::sized_range<R>
146 and (ranges::borrowed_range<R> or is_const_v<T>)
148 and not is_etl_array<R>
149 and not detail::is_span<R>
150 and detail::span_convertible_from<remove_reference_t<ranges::range_reference_t<R>>, T>
151 )
152 // clang-format on
153 explicit(extent != dynamic_extent) constexpr span(R&& r)
154 : _storage{r.data(), ranges::size(r)}
155 {
156 }
157
158 template <detail::span_convertible_from<T> U, size_t N>
159 requires(extent == dynamic_extent or N == dynamic_extent or N == extent)
160 explicit(extent != dynamic_extent and N == dynamic_extent) constexpr span(span<U, N> const& source) noexcept
161 : _storage{source.data(), source.size()}
162 {
163 }
164
166 constexpr span(span const& other) noexcept = default;
167
170 [[nodiscard]] constexpr auto begin() const noexcept -> iterator { return _storage.data(); }
171
175 [[nodiscard]] constexpr auto end() const noexcept -> iterator { return begin() + size(); }
176
180 [[nodiscard]] constexpr auto rbegin() const noexcept -> reverse_iterator { return reverse_iterator(end()); }
181
186 [[nodiscard]] constexpr auto rend() const noexcept -> reverse_iterator { return reverse_iterator(begin()); }
187
190 [[nodiscard]] constexpr auto front() const -> reference
191 {
193 return *begin();
194 }
195
198 [[nodiscard]] constexpr auto back() const -> reference
199 {
201 return *(end() - 1);
202 }
203
207 [[nodiscard]] constexpr auto operator[](size_type idx) const -> reference
208 {
209 TETL_PRECONDITION(idx < size());
210 return data()[idx];
211 }
212
214 [[nodiscard]] constexpr auto data() const noexcept -> pointer { return _storage.data(); }
215
217 [[nodiscard]] constexpr auto size() const noexcept -> size_type { return _storage.size(); }
218
220 [[nodiscard]] constexpr auto size_bytes() const noexcept -> size_type { return size() * sizeof(element_type); }
221
223 [[nodiscard]] constexpr auto empty() const noexcept -> bool { return size() == 0; }
224
227 template <size_t Count>
228 [[nodiscard]] constexpr auto first() const -> span<element_type, Count>
229 {
230 static_assert(Count <= Extent);
231 return span<element_type, Count>{data(), static_cast<size_type>(Count)};
232 }
233
236 [[nodiscard]] constexpr auto first(size_type count) const -> span<element_type, dynamic_extent>
237 {
239 return {data(), static_cast<size_type>(count)};
240 }
241
244 template <size_t Count>
245 [[nodiscard]] constexpr auto last() const -> span<element_type, Count>
246 {
247 static_assert(Count <= Extent);
248 return span<element_type, Count>{data() + (size() - Count), static_cast<size_type>(Count)};
249 }
250
253 [[nodiscard]] constexpr auto last(size_type count) const -> span<element_type, dynamic_extent>
254 {
256 return {data() + (size() - count), static_cast<size_type>(count)};
257 }
258
263 template <size_t Offset, size_t Count = dynamic_extent>
264 [[nodiscard]] constexpr auto subspan() const -> span<T, detail::subspan_extent<Offset, Count, Extent>()>
265 {
266 static_assert(Offset <= Extent);
267 static_assert(Count == dynamic_extent or Count <= Extent - Offset);
268
269 auto const ptr = data() + Offset;
270 auto const sz = static_cast<size_type>(Count == dynamic_extent ? size() - Offset : Count);
272 }
273
278 [[nodiscard]] constexpr auto subspan(size_type offset, size_type count = dynamic_extent) const
280 {
281 TETL_PRECONDITION(offset <= size());
282 TETL_PRECONDITION(count != dynamic_extent ? (count <= size() - offset) : true);
283 auto const sz = count == dynamic_extent ? size() - offset : count;
284 return {data() + offset, static_cast<size_type>(sz)};
285 }
286
287private:
288 struct static_storage {
289 constexpr static_storage() = default;
290 constexpr static_storage(T* ptr, size_type /*sz*/) noexcept
291 : _data{ptr}
292 {
293 }
294
295 [[nodiscard]] constexpr auto data() const noexcept { return _data; }
296 [[nodiscard]] constexpr auto size() const noexcept { return Extent; }
297
298 private:
299 T* _data{nullptr};
300 };
301
302 struct dynamic_storage {
303 constexpr dynamic_storage() = default;
304 constexpr dynamic_storage(T* ptr, size_type sz) noexcept
305 : _data{ptr}
306 , _size{sz}
307 {
308 }
309
310 [[nodiscard]] constexpr auto data() const noexcept { return _data; }
311 [[nodiscard]] constexpr auto size() const noexcept { return _size; }
312
313 private:
314 T* _data{nullptr};
315 etl::size_t _size{0};
316 };
317
319 storage _storage;
320};
321
322// Deduction Guides. From raw array.
323template <typename Type, size_t Extent>
325
326// Deduction Guides. From array<Type, Size>.
327template <typename Type, size_t Size>
329
330// Deduction Guides. From array<Type const, Size>.
331template <typename Type, size_t Size>
333
334// Deduction Guides. From a contiguous range
335template <ranges::range /*ranges::contiguous_range*/ R>
337
338namespace ranges {
339template <typename T, etl::size_t Extent>
340inline constexpr bool enable_borrowed_range<etl::span<T, Extent>> = true;
341}
342
343namespace detail {
344template <typename T, etl::size_t N>
345inline constexpr etl::size_t span_as_bytes_size = N == etl::dynamic_extent ? etl::dynamic_extent : sizeof(T) * N;
346}
347
355template <typename T, size_t N>
357{
358 return {reinterpret_cast<byte const*>(s.data()), s.size_bytes()};
359}
360
369template <typename T, size_t N>
370 requires(not is_const_v<T>)
372{
373 return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
374}
375
376} // namespace etl
377
378#endif // TETL_SPAN_SPAN_HPP
#define TETL_PRECONDITION(...)
Definition check.hpp:16
Definition range.hpp:13
ValueType[Size] c_array
Definition c_array.hpp:12
constexpr bool enable_borrowed_range
Definition enable_borrowed_range.hpp:10
constexpr auto dynamic_extent
etl::dynamic_extent is a constant of type etl::size_t that is used to differentiate etl::span of stat...
Definition dynamic_extent.hpp:14
auto as_bytes(span< T, N > s) noexcept -> span< byte const, detail::span_as_bytes_size< T, N > >
Obtains a view to the object representation of the elements of the span s.
Definition span.hpp:356
auto as_writable_bytes(span< T, N > s) noexcept -> span< byte, detail::span_as_bytes_size< T, N > >
Obtains a view to the object representation of the elements of the span s.
Definition span.hpp:371
typename remove_reference< T >::type remove_reference_t
Definition remove_reference.hpp:28
typename type_identity< T >::type type_identity_t
Definition type_identity.hpp:16
Definition ranges_in_fun_result.hpp:11
Definition adjacent_find.hpp:8
typename conditional< B, T, F >::type conditional_t
Definition conditional.hpp:21
constexpr bool is_const_v
Definition is_const.hpp:20
remove_const_t< remove_volatile_t< T > > remove_cv_t
Definition remove_cv.hpp:22
constexpr bool is_array_v
Definition is_array.hpp:26
constexpr auto is_etl_array
Definition array.hpp:331
TETL_BUILTIN_PTRDIFF ptrdiff_t
etl::ptrdiff_t is the signed integer type of the result of subtracting two pointers.
Definition ptrdiff_t.hpp:14
span(c_array< Type, Extent > &) -> span< Type, Extent >
decltype(*etl::declval< T & >()) iter_reference_t
Definition iter_reference_t.hpp:12
constexpr bool is_convertible_v
Definition is_convertible.hpp:46
TETL_BUILTIN_SIZET size_t
etl::size_t is the unsigned integer type of the result of the sizeof operator.
Definition size_t.hpp:14
A container that encapsulates fixed size arrays.
Definition array.hpp:48
array(T, U...) -> array< T, 1+sizeof...(U)>
One deduction guide is provided for array to provide an equivalent of experimental::make_array for co...
reverse_iterator is an iterator adaptor that reverses the direction of a given iterator....
Definition reverse_iterator.hpp:22
A non-owning view over a contiguous sequence of objects.
Definition span.hpp:83
static constexpr size_type extent
The number of elements in the sequence, or etl::dynamic_extent if dynamic.
Definition span.hpp:97
T & reference
Definition span.hpp:90
constexpr auto subspan(size_type offset, size_type count=dynamic_extent) const -> span< T, dynamic_extent >
Obtains a span that is a view over the Count elements of this span starting at offset Offset....
Definition span.hpp:278
constexpr auto rbegin() const noexcept -> reverse_iterator
Returns a reverse iterator to the first element of the reversed span. It corresponds to the last elem...
Definition span.hpp:180
constexpr auto last() const -> span< element_type, Count >
Obtains a span that is a view over the last Count elements of this span. The program is ill-formed if...
Definition span.hpp:245
etl::ptrdiff_t difference_type
Definition span.hpp:87
explicit(extent !=dynamic_extent) const expr span(It first
Constructs a span.
etl::size_t size_type
Definition span.hpp:86
constexpr auto size_bytes() const noexcept -> size_type
Returns the number of elements in the span.
Definition span.hpp:220
T * iterator
Definition span.hpp:92
constexpr auto rend() const noexcept -> reverse_iterator
Returns a reverse iterator to the element following the last element of the reversed span....
Definition span.hpp:186
size_type count
Definition span.hpp:113
constexpr auto subspan() const -> span< T, detail::subspan_extent< Offset, Count, Extent >()>
Obtains a span that is a view over the Count elements of this span starting at offset Offset....
Definition span.hpp:264
constexpr auto end() const noexcept -> iterator
Returns an iterator to the element following the last element of the span. This element acts as a pla...
Definition span.hpp:175
constexpr auto operator[](size_type idx) const -> reference
Returns a reference to the idx-th element of the sequence. The behavior is undefined if idx is out of...
Definition span.hpp:207
constexpr auto first() const -> span< element_type, Count >
Obtains a span that is a view over the first Count elements of this span. The program is ill-formed i...
Definition span.hpp:228
constexpr auto data() const noexcept -> pointer
Returns a pointer to the beginning of the sequence.
Definition span.hpp:214
constexpr auto begin() const noexcept -> iterator
Returns an iterator to the first element of the span. If the span is empty, the returned iterator wil...
Definition span.hpp:170
constexpr auto empty() const noexcept -> bool
Checks if the span is empty.
Definition span.hpp:223
etl::reverse_iterator< iterator > reverse_iterator
Definition span.hpp:93
constexpr auto last(size_type count) const -> span< element_type, dynamic_extent >
Obtains a span that is a view over the last Count elements of this span. The behavior is undefined if...
Definition span.hpp:253
T * pointer
Definition span.hpp:88
T element_type
Definition span.hpp:84
constexpr auto back() const -> reference
Returns a reference to the last element in the span. Calling front on an empty span results in undefi...
Definition span.hpp:198
constexpr auto first(size_type count) const -> span< element_type, dynamic_extent >
Obtains a span that is a view over the first Count elements of this span. The behavior is undefined i...
Definition span.hpp:236
T const * const_pointer
Definition span.hpp:89
etl::remove_cv_t< T > value_type
Definition span.hpp:85
constexpr auto front() const -> reference
Returns a reference to the first element in the span. Calling front on an empty span results in undef...
Definition span.hpp:190
constexpr auto size() const noexcept -> size_type
Returns the number of elements in the span.
Definition span.hpp:217
T const & const_reference
Definition span.hpp:91
constexpr span() noexcept=default
Constructs a span. Constructs an empty span whose data() == nullptr and size() == 0.