CTRE Phoenix 6 C++ 25.0.0-beta-4
Loading...
Searching...
No Matches
span.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) Cross The Road Electronics.  All rights reserved.
3 * License information can be found in CTRE_LICENSE.txt
4 * For support and suggestions contact support@ctr-electronics.com or file
5 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases
6 */
7
8/*
9This is an implementation of C++20's std::span
10http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4820.pdf
11*/
12
13// Copyright Tristan Brindle 2018.
14// Distributed under the Boost Software License, Version 1.0.
15// (See accompanying file ../../LICENSE_1_0.txt or copy at
16// https://www.boost.org/LICENSE_1_0.txt)
17
18#pragma once
19
20#if __cpp_lib_span >= 202002L
21
22#include <span>
23
24namespace ctre {
25namespace phoenix6 {
26namespace swerve {
27
28using std::span;
29
30}
31}
32}
33
34#else
35
36#include <array>
37#include <cassert>
38#include <cstddef>
39#include <cstdint>
40#include <type_traits>
41
42namespace ctre {
43namespace phoenix6 {
44namespace swerve {
45
46inline constexpr std::size_t dynamic_extent = SIZE_MAX;
47
48template <typename ElementType, std::size_t Extent = dynamic_extent>
49class span;
50
51namespace detail {
52
53template <typename E, std::size_t S>
55 constexpr span_storage() noexcept = default;
56
57 constexpr span_storage(E* p_ptr, std::size_t /*unused*/) noexcept
58 : ptr(p_ptr)
59 {}
60
61 E* ptr = nullptr;
62 static constexpr std::size_t size = S;
63};
64
65template <typename E>
67 constexpr span_storage() noexcept = default;
68
69 constexpr span_storage(E* p_ptr, std::size_t p_size) noexcept
70 : ptr(p_ptr), size(p_size)
71 {}
72
73 E* ptr = nullptr;
74 std::size_t size = 0;
75};
76
77template <typename T>
78using uncvref_t =
79 typename std::remove_cv<typename std::remove_reference<T>::type>::type;
80
81template <typename>
82struct is_span : std::false_type {};
83
84template <typename T, std::size_t S>
85struct is_span<span<T, S>> : std::true_type {};
86
87template <typename>
88struct is_std_array : std::false_type {};
89
90template <typename T, std::size_t N>
91struct is_std_array<std::array<T, N>> : std::true_type {};
92
93template <typename, typename = void>
94struct has_size_and_data : std::false_type {};
95
96template <typename T>
97struct has_size_and_data<T, std::void_t<decltype(std::size(std::declval<T>())),
98 decltype(std::data(std::declval<T>()))>>
99 : std::true_type {};
100
101template <typename C, typename U = uncvref_t<C>>
103 static constexpr bool value =
105 !std::is_array<U>::value && has_size_and_data<C>::value;
106};
107
108template <typename T>
109using remove_pointer_t = typename std::remove_pointer<T>::type;
110
111template <typename, typename, typename = void>
112struct is_container_element_type_compatible : std::false_type {};
113
114template <typename T, typename E>
116 T, E,
117 typename std::enable_if<
118 !std::is_same<typename std::remove_cv<decltype(
119 std::data(std::declval<T>()))>::type,
120 void>::value>::type>
121 : std::is_convertible<
122 remove_pointer_t<decltype(std::data(std::declval<T>()))> (*)[],
123 E (*)[]> {};
124
125template <typename, typename = size_t>
126struct is_complete : std::false_type {};
127
128template <typename T>
129struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
130
131} // namespace detail
132
133template <typename ElementType, std::size_t Extent>
134class span {
135 static_assert(std::is_object<ElementType>::value,
136 "A span's ElementType must be an object type (not a "
137 "reference type or void)");
139 "A span's ElementType must be a complete type (not a forward "
140 "declaration)");
141 static_assert(!std::is_abstract<ElementType>::value,
142 "A span's ElementType cannot be an abstract class type");
143
145
146public:
147 // constants and types
148 using element_type = ElementType;
149 using value_type = typename std::remove_cv<ElementType>::type;
150 using size_type = std::size_t;
151 using difference_type = std::ptrdiff_t;
157 using reverse_iterator = std::reverse_iterator<iterator>;
158
159 static constexpr size_type extent = Extent;
160
161 // [span.cons], span constructors, copy, assignment, and destructor
162 template <
163 std::size_t E = Extent,
164 typename std::enable_if<(E == dynamic_extent || E <= 0), int>::type = 0>
165 constexpr span() noexcept
166 {}
167
168 constexpr span(pointer ptr, size_type count)
169 : storage_(ptr, count)
170 {
171 assert(extent == dynamic_extent || count == extent);
172 }
173
174 constexpr span(pointer first_elem, pointer last_elem)
175 : storage_(first_elem, last_elem - first_elem)
176 {
177 assert(extent == dynamic_extent ||
178 last_elem - first_elem ==
179 static_cast<std::ptrdiff_t>(extent));
180 }
181
182 template <std::size_t N, std::size_t E = Extent,
183 typename std::enable_if<
184 (E == dynamic_extent || N == E) &&
186 element_type (&)[N], ElementType>::value,
187 int>::type = 0>
188 constexpr span(element_type (&arr)[N]) noexcept : storage_(arr, N)
189 {}
190
191 template <std::size_t N, std::size_t E = Extent,
192 typename std::enable_if<
193 (E == dynamic_extent || N == E) &&
195 std::array<value_type, N>&, ElementType>::value,
196 int>::type = 0>
197 constexpr span(std::array<value_type, N>& arr) noexcept
198 : storage_(arr.data(), N)
199 {}
200
201 template <std::size_t N, std::size_t E = Extent,
202 typename std::enable_if<
203 (E == dynamic_extent || N == E) &&
205 const std::array<value_type, N>&, ElementType>::value,
206 int>::type = 0>
207 constexpr span(const std::array<value_type, N>& arr) noexcept
208 : storage_(arr.data(), N)
209 {}
210
211 template <
212 typename Container, std::size_t E = Extent,
213 typename std::enable_if<
216 Container&, ElementType>::value,
217 int>::type = 0>
218 constexpr span(Container& cont)
219 : storage_(std::data(cont), std::size(cont))
220 {}
221
222 template <
223 typename Container, std::size_t E = Extent,
224 typename std::enable_if<
227 const Container&, ElementType>::value,
228 int>::type = 0>
229 constexpr span(const Container& cont)
230 : storage_(std::data(cont), std::size(cont))
231 {}
232
233 constexpr span(const span& other) noexcept = default;
234
235 template <typename OtherElementType, std::size_t OtherExtent,
236 typename std::enable_if<
237 (Extent == OtherExtent || Extent == dynamic_extent) &&
238 std::is_convertible<OtherElementType (*)[],
239 ElementType (*)[]>::value,
240 int>::type = 0>
241 constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
242 : storage_(other.data(), other.size())
243 {}
244
245 ~span() noexcept = default;
246
247 constexpr span&
248 operator=(const span& other) noexcept = default;
249
250 // [span.sub], span subviews
251 template <std::size_t Count>
252 constexpr span<element_type, Count> first() const
253 {
254 assert(Count <= size());
255 return {data(), Count};
256 }
257
258 template <std::size_t Count>
260 {
261 assert(Count <= size());
262 return {data() + (size() - Count), Count};
263 }
264
265 template <std::size_t Offset, std::size_t Count = dynamic_extent>
267 span<ElementType, Count != dynamic_extent
268 ? Count
269 : (Extent != dynamic_extent ? Extent - Offset
270 : dynamic_extent)>;
271
272 template <std::size_t Offset, std::size_t Count = dynamic_extent>
274 {
275 assert(Offset <= size() &&
276 (Count == dynamic_extent || Offset + Count <= size()));
277 return {data() + Offset,
278 Count != dynamic_extent ? Count : size() - Offset};
279 }
280
282 first(size_type count) const
283 {
284 assert(count <= size());
285 return {data(), count};
286 }
287
289 last(size_type count) const
290 {
291 assert(count <= size());
292 return {data() + (size() - count), count};
293 }
294
297 {
298 assert(offset <= size() &&
299 (count == dynamic_extent || offset + count <= size()));
300 return {data() + offset,
301 count == dynamic_extent ? size() - offset : count};
302 }
303
304 // [span.obs], span observers
305 constexpr size_type size() const noexcept { return storage_.size; }
306
307 constexpr size_type size_bytes() const noexcept
308 {
309 return size() * sizeof(element_type);
310 }
311
312 [[nodiscard]] constexpr bool empty() const noexcept
313 {
314 return size() == 0;
315 }
316
317 // [span.elem], span element access
318 constexpr reference operator[](size_type idx) const
319 {
320 assert(idx < size());
321 return *(data() + idx);
322 }
323
324 constexpr reference front() const
325 {
326 assert(!empty());
327 return *data();
328 }
329
330 constexpr reference back() const
331 {
332 assert(!empty());
333 return *(data() + (size() - 1));
334 }
335
336 constexpr pointer data() const noexcept { return storage_.ptr; }
337
338 // [span.iterators], span iterator support
339 constexpr iterator begin() const noexcept { return data(); }
340
341 constexpr iterator end() const noexcept { return data() + size(); }
342
343 constexpr reverse_iterator rbegin() const noexcept
344 {
345 return reverse_iterator(end());
346 }
347
348 constexpr reverse_iterator rend() const noexcept
349 {
350 return reverse_iterator(begin());
351 }
352
353private:
354 storage_type storage_{};
355};
356
357/* Deduction Guides */
358template <class T, size_t N>
359span(T (&)[N])->span<T, N>;
360
361template <class T, size_t N>
362span(std::array<T, N>&)->span<T, N>;
363
364template <class T, size_t N>
365span(const std::array<T, N>&)->span<const T, N>;
366
367template <class Container>
368span(Container&)->span<typename Container::value_type>;
369
370template <class Container>
371span(const Container&)->span<const typename Container::value_type>;
372
373template <typename ElementType, std::size_t Extent>
374span<const std::byte, ((Extent == dynamic_extent) ? dynamic_extent
375 : sizeof(ElementType) * Extent)>
376as_bytes(span<ElementType, Extent> s) noexcept
377{
378 return {reinterpret_cast<const std::byte*>(s.data()), s.size_bytes()};
379}
380
381template <
382 class ElementType, size_t Extent,
383 typename std::enable_if<!std::is_const<ElementType>::value, int>::type = 0>
384span<std::byte, ((Extent == dynamic_extent) ? dynamic_extent
385 : sizeof(ElementType) * Extent)>
386as_writable_bytes(span<ElementType, Extent> s) noexcept
387{
388 return {reinterpret_cast<std::byte*>(s.data()), s.size_bytes()};
389}
390
391template <std::size_t N, typename E, std::size_t S>
392constexpr auto get(span<E, S> s) -> decltype(s[N])
393{
394 return s[N];
395}
396
397}
398}
399}
400
401namespace std {
402
403template <typename ElementType, size_t Extent>
404class tuple_size<ctre::phoenix6::swerve::span<ElementType, Extent>>
405 : public integral_constant<size_t, Extent> {};
406
407template <typename ElementType>
408class tuple_size<ctre::phoenix6::swerve::span<
409 ElementType, ctre::phoenix6::swerve::dynamic_extent>>; // not defined
410
411template <size_t I, typename ElementType, size_t Extent>
412class tuple_element<I, ctre::phoenix6::swerve::span<ElementType, Extent>> {
413public:
414 static_assert(Extent != ctre::phoenix6::swerve::dynamic_extent &&
415 I < Extent,
416 "");
417 using type = ElementType;
418};
419
420}
421
422#endif
Definition span.hpp:134
constexpr span< element_type, Count > last() const
Definition span.hpp:259
constexpr subspan_return_t< Offset, Count > subspan() const
Definition span.hpp:273
constexpr span() noexcept
Definition span.hpp:165
std::size_t size_type
Definition span.hpp:150
constexpr reference back() const
Definition span.hpp:330
element_type & reference
Definition span.hpp:154
constexpr span(const std::array< value_type, N > &arr) noexcept
Definition span.hpp:207
constexpr pointer data() const noexcept
Definition span.hpp:336
typename std::remove_cv< ElementType >::type value_type
Definition span.hpp:149
std::reverse_iterator< iterator > reverse_iterator
Definition span.hpp:157
constexpr span< element_type, Count > first() const
Definition span.hpp:252
constexpr iterator begin() const noexcept
Definition span.hpp:339
const element_type * const_pointer
Definition span.hpp:153
constexpr span(Container &cont)
Definition span.hpp:218
const element_type & const_reference
Definition span.hpp:155
constexpr reference front() const
Definition span.hpp:324
std::ptrdiff_t difference_type
Definition span.hpp:151
constexpr bool empty() const noexcept
Definition span.hpp:312
pointer iterator
Definition span.hpp:156
constexpr span(pointer first_elem, pointer last_elem)
Definition span.hpp:174
constexpr span(std::array< value_type, N > &arr) noexcept
Definition span.hpp:197
constexpr span< element_type, dynamic_extent > subspan(size_type offset, size_type count=dynamic_extent) const
Definition span.hpp:296
constexpr size_type size_bytes() const noexcept
Definition span.hpp:307
constexpr span(element_type(&arr)[N]) noexcept
Definition span.hpp:188
~span() noexcept=default
constexpr iterator end() const noexcept
Definition span.hpp:341
ElementType element_type
Definition span.hpp:148
constexpr reverse_iterator rbegin() const noexcept
Definition span.hpp:343
constexpr span(const span &other) noexcept=default
constexpr reference operator[](size_type idx) const
Definition span.hpp:318
element_type * pointer
Definition span.hpp:152
constexpr span(pointer ptr, size_type count)
Definition span.hpp:168
constexpr size_type size() const noexcept
Definition span.hpp:305
constexpr span< element_type, dynamic_extent > first(size_type count) const
Definition span.hpp:282
constexpr span(const span< OtherElementType, OtherExtent > &other) noexcept
Definition span.hpp:241
constexpr span< element_type, dynamic_extent > last(size_type count) const
Definition span.hpp:289
constexpr span(const Container &cont)
Definition span.hpp:229
constexpr reverse_iterator rend() const noexcept
Definition span.hpp:348
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition span.hpp:78
typename std::remove_pointer< T >::type remove_pointer_t
Definition span.hpp:109
span< std::byte,((Extent==dynamic_extent) ? dynamic_extent :sizeof(ElementType) *Extent)> as_writable_bytes(span< ElementType, Extent > s) noexcept
Definition span.hpp:386
constexpr std::size_t dynamic_extent
Definition span.hpp:46
span< const std::byte,((Extent==dynamic_extent) ? dynamic_extent :sizeof(ElementType) *Extent)> as_bytes(span< ElementType, Extent > s) noexcept
Definition span.hpp:376
span(T(&)[N]) -> span< T, N >
constexpr auto get(span< E, S > s) -> decltype(s[N])
Definition span.hpp:392
Definition StatusCodes.h:18
Definition span.hpp:401
static constexpr bool value
Definition span.hpp:103
static constexpr std::size_t size
Definition span.hpp:62
constexpr span_storage() noexcept=default