aligator 0.17.1
A versatile and efficient C++ library for real-time constrained trajectory optimization.
Loading...
Searching...
No Matches
span.hpp
Go to the documentation of this file.
1/*
2Copyright 2019-2023 Glen Joseph Fernandes
3(glenjofe@gmail.com)
4
5Distributed under the Boost Software License, Version 1.0.
6(http://www.boost.org/LICENSE_1_0.txt)
7*/
8#ifndef BOOST_CORE_SPAN_HPP
9#define BOOST_CORE_SPAN_HPP
10
13
14#include <array>
15#include <iterator>
16#include <type_traits>
17
18namespace boost {
19
20constexpr std::size_t dynamic_extent = static_cast<std::size_t>(-1);
21
22template <class T, std::size_t E = dynamic_extent> class span;
23
24namespace detail {
25
26template <class U, class T, class = void> struct span_convertible {
27 static constexpr bool value = false;
28};
29
30template <class U, class T>
31struct span_convertible<U, T,
32 typename std::enable_if<std::is_convertible<
33 U (*)[], T (*)[]>::value>::type> {
34 static constexpr bool value = true;
35};
36
37template <std::size_t E, std::size_t N> struct span_capacity {
38 static constexpr bool value = E == boost::dynamic_extent || E == N;
39};
40
41template <class T, std::size_t E, class U, std::size_t N>
42struct span_compatible {
43 static constexpr bool value =
44 span_capacity<E, N>::value && span_convertible<U, T>::value;
45};
46
47template <class T>
48using span_uncvref =
49 typename std::remove_cv<typename std::remove_reference<T>::type>::type;
50
51template <class> struct span_is_span {
52 static constexpr bool value = false;
53};
54
55template <class T, std::size_t E> struct span_is_span<boost::span<T, E>> {
56 static constexpr bool value = true;
57};
58
59template <class T> struct span_is_array {
60 static constexpr bool value = false;
61};
62
63template <class T, std::size_t N> struct span_is_array<std::array<T, N>> {
64 static constexpr bool value = true;
65};
66
67template <class T> using span_ptr = decltype(boost::data(std::declval<T &>()));
68
69template <class, class = void> struct span_data {};
70
71template <class T>
72struct span_data<
73 T, typename std::enable_if<std::is_pointer<span_ptr<T>>::value>::type> {
74 typedef typename std::remove_pointer<span_ptr<T>>::type type;
75};
76
77template <class, class, class = void> struct span_has_data {
78 static constexpr bool value = false;
79};
80
81template <class R, class T>
82struct span_has_data<R, T,
83 typename std::enable_if<span_convertible<
84 typename span_data<R>::type, T>::value>::type> {
85 static constexpr bool value = true;
86};
87
88template <class, class = void> struct span_has_size {
89 static constexpr bool value = false;
90};
91
92template <class R>
93struct span_has_size<
94 R, typename std::enable_if<std::is_convertible<
95 decltype(std::declval<R &>().size()), std::size_t>::value>::type> {
96 static constexpr bool value = true;
97};
98
99template <class R, class T> struct span_is_range {
100 static constexpr bool value =
101 (std::is_const<T>::value || std::is_lvalue_reference<R>::value) &&
102 !span_is_span<span_uncvref<R>>::value &&
103 !span_is_array<span_uncvref<R>>::value &&
104 !std::is_array<span_uncvref<R>>::value && span_has_data<R, T>::value &&
105 span_has_size<R>::value;
106};
107
108template <std::size_t E, std::size_t N> struct span_implicit {
109 static constexpr bool value =
110 E == boost::dynamic_extent || N != boost::dynamic_extent;
111};
112
113template <class T, std::size_t E, class U, std::size_t N> struct span_copyable {
114 static constexpr bool value =
115 (N == boost::dynamic_extent || span_capacity<E, N>::value) &&
116 span_convertible<U, T>::value;
117};
118
119template <std::size_t E, std::size_t O> struct span_sub {
120 static constexpr std::size_t value =
121 E == boost::dynamic_extent ? boost::dynamic_extent : E - O;
122};
123
124template <class T, std::size_t E> struct span_store {
125 constexpr span_store(T *p_, std::size_t) noexcept
126 : p(p_) {}
127 static constexpr std::size_t n = E;
128 T *p;
129};
130
131template <class T> struct span_store<T, boost::dynamic_extent> {
132 constexpr span_store(T *p_, std::size_t n_) noexcept
133 : p(p_)
134 , n(n_) {}
135 T *p;
136 std::size_t n;
137};
138
139template <class T, std::size_t E> struct span_bytes {
140 static constexpr std::size_t value = sizeof(T) * E;
141};
142
143template <class T> struct span_bytes<T, boost::dynamic_extent> {
144 static constexpr std::size_t value = boost::dynamic_extent;
145};
146
147} // namespace detail
148
149template <class T, std::size_t E> class span {
150public:
151 typedef T element_type;
152 typedef typename std::remove_cv<T>::type value_type;
153 typedef std::size_t size_type;
154 typedef std::ptrdiff_t difference_type;
155 typedef T *pointer;
156 typedef const T *const_pointer;
157 typedef T &reference;
158 typedef const T &const_reference;
159 typedef T *iterator;
160 typedef const T *const_iterator;
161 typedef std::reverse_iterator<T *> reverse_iterator;
162 typedef std::reverse_iterator<const T *> const_reverse_iterator;
163
164 static constexpr std::size_t extent = E;
165
166 template <
167 std::size_t N = E,
168 typename std::enable_if<N == dynamic_extent || N == 0, int>::type = 0>
169 constexpr span() noexcept
170 : s_(0, 0) {}
171
172 template <class I,
173 typename std::enable_if<E == dynamic_extent &&
174 detail::span_convertible<I, T>::value,
175 int>::type = 0>
176 constexpr span(I *f, size_type c)
177 : s_(f, c) {}
178
179 template <class I,
180 typename std::enable_if<E != dynamic_extent &&
181 detail::span_convertible<I, T>::value,
182 int>::type = 0>
183 explicit constexpr span(I *f, size_type c)
184 : s_(f, c) {}
185
186 template <class I, class L,
187 typename std::enable_if<E == dynamic_extent &&
188 detail::span_convertible<I, T>::value,
189 int>::type = 0>
190 constexpr span(I *f, L *l)
191 : s_(f, l - f) {}
192
193 template <class I, class L,
194 typename std::enable_if<E != dynamic_extent &&
195 detail::span_convertible<I, T>::value,
196 int>::type = 0>
197 explicit constexpr span(I *f, L *l)
198 : s_(f, l - f) {}
199
200 template <std::size_t N,
201 typename std::enable_if<detail::span_capacity<E, N>::value,
202 int>::type = 0>
203 constexpr span(typename std::enable_if<true, T>::type (&a)[N]) noexcept
204 : s_(a, N) {}
205
206 template <class U, std::size_t N,
207 typename std::enable_if<detail::span_compatible<T, E, U, N>::value,
208 int>::type = 0>
209 constexpr span(std::array<U, N> &a) noexcept
210 : s_(a.data(), N) {}
211
212 template <
213 class U, std::size_t N,
214 typename std::enable_if<detail::span_compatible<T, E, const U, N>::value,
215 int>::type = 0>
216 constexpr span(const std::array<U, N> &a) noexcept
217 : s_(a.data(), N) {}
218
219 template <class R,
220 typename std::enable_if<E == dynamic_extent &&
221 detail::span_is_range<R, T>::value,
222 int>::type = 0>
223 constexpr span(R &&r) noexcept(noexcept(boost::data(r)) && noexcept(r.size()))
224 : s_(boost::data(r), r.size()) {}
225
226 template <class R,
227 typename std::enable_if<E != dynamic_extent &&
228 detail::span_is_range<R, T>::value,
229 int>::type = 0>
230 explicit constexpr span(R &&r) noexcept(noexcept(boost::data(r)) &&
231 noexcept(r.size()))
232 : s_(boost::data(r), r.size()) {}
233
234 template <
235 class U, std::size_t N,
236 typename std::enable_if<detail::span_implicit<E, N>::value &&
237 detail::span_copyable<T, E, U, N>::value,
238 int>::type = 0>
239 constexpr span(const span<U, N> &s) noexcept
240 : s_(s.data(), s.size()) {}
241
242 template <
243 class U, std::size_t N,
244 typename std::enable_if<!detail::span_implicit<E, N>::value &&
245 detail::span_copyable<T, E, U, N>::value,
246 int>::type = 0>
247 explicit constexpr span(const span<U, N> &s) noexcept
248 : s_(s.data(), s.size()) {}
249
250 template <std::size_t C> constexpr span<T, C> first() const {
251 static_assert(C <= E, "Count <= Extent");
252 return span<T, C>(s_.p, C);
253 }
254
255 template <std::size_t C> constexpr span<T, C> last() const {
256 static_assert(C <= E, "Count <= Extent");
257 return span<T, C>(s_.p + (s_.n - C), C);
258 }
259
260 template <std::size_t O, std::size_t C = dynamic_extent>
261 constexpr
262 typename std::enable_if<C == dynamic_extent,
263 span<T, detail::span_sub<E, O>::value>>::type
264 subspan() const {
265 static_assert(O <= E, "Offset <= Extent");
266 return span<T, detail::span_sub<E, O>::value>(s_.p + O, s_.n - O);
267 }
268
269 template <std::size_t O, std::size_t C = dynamic_extent>
270 constexpr typename std::enable_if<C != dynamic_extent, span<T, C>>::type
271 subspan() const {
272 static_assert(O <= E && C <= E - O,
273 "Offset <= Extent && Count <= Extent - Offset");
274 return span<T, C>(s_.p + O, C);
275 }
276
277 constexpr span<T, dynamic_extent> first(size_type c) const {
278 return BOOST_CORE_DETAIL_ASSERT(c <= size()),
279 span<T, dynamic_extent>(s_.p, c);
280 }
281
282 constexpr span<T, dynamic_extent> last(size_type c) const {
283 return BOOST_CORE_DETAIL_ASSERT(c <= size()),
284 span<T, dynamic_extent>(s_.p + (s_.n - c), c);
285 }
286
287 constexpr span<T, dynamic_extent>
288 subspan(size_type o, size_type c = dynamic_extent) const {
289 return BOOST_CORE_DETAIL_ASSERT(o <= size() &&
290 (c == dynamic_extent || c + o <= size())),
291 span<T, dynamic_extent>(s_.p + o,
292 c == dynamic_extent ? s_.n - o : c);
293 }
294
295 constexpr size_type size() const noexcept { return s_.n; }
296
297 constexpr size_type size_bytes() const noexcept { return s_.n * sizeof(T); }
298
299 constexpr bool empty() const noexcept { return s_.n == 0; }
300
301 constexpr reference operator[](size_type i) const {
302 return BOOST_CORE_DETAIL_ASSERT(i < size()), s_.p[i];
303 }
304
305 constexpr reference front() const {
306 return BOOST_CORE_DETAIL_ASSERT(!empty()), *s_.p;
307 }
308
309 constexpr reference back() const {
310 return BOOST_CORE_DETAIL_ASSERT(!empty()), s_.p[s_.n - 1];
311 }
312
313 constexpr pointer data() const noexcept { return s_.p; }
314
315 constexpr iterator begin() const noexcept { return s_.p; }
316
317 constexpr iterator end() const noexcept { return s_.p + s_.n; }
318
319 constexpr reverse_iterator rbegin() const noexcept {
320 return reverse_iterator(s_.p + s_.n);
321 }
322
323 constexpr reverse_iterator rend() const noexcept {
324 return reverse_iterator(s_.p);
325 }
326
327 constexpr const_iterator cbegin() const noexcept { return s_.p; }
328
329 constexpr const_iterator cend() const noexcept { return s_.p + s_.n; }
330
331 constexpr const_reverse_iterator crbegin() const noexcept {
332 return const_reverse_iterator(s_.p + s_.n);
333 }
334
335 constexpr const_reverse_iterator crend() const noexcept {
336 return const_reverse_iterator(s_.p);
337 }
338
339private:
340 detail::span_store<T, E> s_;
341};
342
343#if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
344template <class T, std::size_t E> constexpr std::size_t span<T, E>::extent;
345#endif
346
347#ifdef __cpp_deduction_guides
348template <class I, class L> span(I *, L) -> span<I>;
349
350template <class T, std::size_t N> span(T (&)[N]) -> span<T, N>;
351
352template <class T, std::size_t N> span(std::array<T, N> &) -> span<T, N>;
353
354template <class T, std::size_t N>
355span(const std::array<T, N> &) -> span<const T, N>;
356
357template <class R> span(R &&) -> span<typename detail::span_data<R>::type>;
358
359template <class T, std::size_t E> span(span<T, E>) -> span<T, E>;
360#endif
361
362#ifdef __cpp_lib_byte
363template <class T, std::size_t E>
364inline span<const std::byte, detail::span_bytes<T, E>::value>
365as_bytes(span<T, E> s) noexcept {
366 return span<const std::byte, detail::span_bytes<T, E>::value>(
367 reinterpret_cast<const std::byte *>(s.data()), s.size_bytes());
368}
369
370template <class T, std::size_t E>
371inline typename std::enable_if<
372 !std::is_const<T>::value,
373 span<std::byte, detail::span_bytes<T, E>::value>>::type
374as_writable_bytes(span<T, E> s) noexcept {
375 return span<std::byte, detail::span_bytes<T, E>::value>(
376 reinterpret_cast<std::byte *>(s.data()), s.size_bytes());
377}
378#endif
379
380} // namespace boost
381
382#endif
#define BOOST_CORE_DETAIL_ASSERT(expr)
Definition assert.hpp:15