8#ifndef BOOST_CORE_SPAN_HPP
9#define BOOST_CORE_SPAN_HPP
20constexpr std::size_t dynamic_extent =
static_cast<std::size_t
>(-1);
22template <
class T, std::
size_t E = dynamic_extent>
class span;
26template <
class U,
class T,
class =
void>
struct span_convertible {
27 static constexpr bool value =
false;
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;
37template <std::
size_t E, std::
size_t N>
struct span_capacity {
38 static constexpr bool value = E == boost::dynamic_extent || E == N;
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;
49 typename std::remove_cv<typename std::remove_reference<T>::type>::type;
51template <
class>
struct span_is_span {
52 static constexpr bool value =
false;
55template <
class T, std::
size_t E>
struct span_is_span<boost::span<T, E>> {
56 static constexpr bool value =
true;
59template <
class T>
struct span_is_array {
60 static constexpr bool value =
false;
63template <
class T, std::
size_t N>
struct span_is_array<std::array<T, N>> {
64 static constexpr bool value =
true;
67template <
class T>
using span_ptr =
decltype(boost::data(std::declval<T &>()));
69template <
class,
class =
void>
struct 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;
77template <
class,
class,
class =
void>
struct span_has_data {
78 static constexpr bool value =
false;
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;
88template <
class,
class =
void>
struct span_has_size {
89 static constexpr bool value =
false;
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;
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;
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;
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;
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;
124template <
class T, std::
size_t E>
struct span_store {
125 constexpr span_store(T *p_, std::size_t) noexcept
127 static constexpr std::size_t n = E;
131template <
class T>
struct span_store<T, boost::dynamic_extent> {
132 constexpr span_store(T *p_, std::size_t n_) noexcept
139template <
class T, std::
size_t E>
struct span_bytes {
140 static constexpr std::size_t value =
sizeof(T) * E;
143template <
class T>
struct span_bytes<T, boost::dynamic_extent> {
144 static constexpr std::size_t value = boost::dynamic_extent;
149template <
class T, std::
size_t E>
class span {
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;
156 typedef const T *const_pointer;
157 typedef T &reference;
158 typedef const T &const_reference;
160 typedef const T *const_iterator;
161 typedef std::reverse_iterator<T *> reverse_iterator;
162 typedef std::reverse_iterator<const T *> const_reverse_iterator;
164 static constexpr std::size_t extent = E;
168 typename std::enable_if<N == dynamic_extent || N == 0, int>::type = 0>
169 constexpr span() noexcept
173 typename std::enable_if<E == dynamic_extent &&
174 detail::span_convertible<I, T>::value,
176 constexpr span(I *f, size_type c)
180 typename std::enable_if<E != dynamic_extent &&
181 detail::span_convertible<I, T>::value,
183 explicit constexpr span(I *f, size_type c)
186 template <
class I,
class L,
187 typename std::enable_if<E == dynamic_extent &&
188 detail::span_convertible<I, T>::value,
190 constexpr span(I *f, L *l)
193 template <
class I,
class L,
194 typename std::enable_if<E != dynamic_extent &&
195 detail::span_convertible<I, T>::value,
197 explicit constexpr span(I *f, L *l)
200 template <std::size_t N,
201 typename std::enable_if<detail::span_capacity<E, N>::value,
203 constexpr span(
typename std::enable_if<true, T>::type (&a)[N]) noexcept
206 template <
class U, std::size_t N,
207 typename std::enable_if<detail::span_compatible<T, E, U, N>::value,
209 constexpr span(std::array<U, N> &a) noexcept
213 class U, std::size_t N,
214 typename std::enable_if<detail::span_compatible<T, E, const U, N>::value,
216 constexpr span(
const std::array<U, N> &a) noexcept
220 typename std::enable_if<E == dynamic_extent &&
221 detail::span_is_range<R, T>::value,
223 constexpr span(R &&r)
noexcept(
noexcept(boost::data(r)) &&
noexcept(r.size()))
224 : s_(boost::data(r), r.size()) {}
227 typename std::enable_if<E != dynamic_extent &&
228 detail::span_is_range<R, T>::value,
230 explicit constexpr span(R &&r)
noexcept(
noexcept(boost::data(r)) &&
232 : s_(boost::data(r), r.size()) {}
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,
239 constexpr span(
const span<U, N> &s) noexcept
240 : s_(s.data(), s.size()) {}
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,
247 explicit constexpr span(
const span<U, N> &s) noexcept
248 : s_(s.data(), s.size()) {}
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);
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);
260 template <std::
size_t O, std::
size_t C = dynamic_extent>
262 typename std::enable_if<C == dynamic_extent,
263 span<T, detail::span_sub<E, O>::value>>::type
265 static_assert(O <= E,
"Offset <= Extent");
266 return span<T, detail::span_sub<E, O>::value>(s_.p + O, s_.n - O);
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
272 static_assert(O <= E && C <= E - O,
273 "Offset <= Extent && Count <= Extent - Offset");
274 return span<T, C>(s_.p + O, C);
277 constexpr span<T, dynamic_extent> first(size_type c)
const {
279 span<T, dynamic_extent>(s_.p, c);
282 constexpr span<T, dynamic_extent> last(size_type c)
const {
284 span<T, dynamic_extent>(s_.p + (s_.n - c), c);
287 constexpr span<T, dynamic_extent>
288 subspan(size_type o, size_type c = dynamic_extent)
const {
290 (c == dynamic_extent || c + o <= size())),
291 span<T, dynamic_extent>(s_.p + o,
292 c == dynamic_extent ? s_.n - o : c);
295 constexpr size_type size() const noexcept {
return s_.n; }
297 constexpr size_type size_bytes() const noexcept {
return s_.n *
sizeof(T); }
299 constexpr bool empty() const noexcept {
return s_.n == 0; }
301 constexpr reference operator[](size_type i)
const {
305 constexpr reference front()
const {
309 constexpr reference back()
const {
313 constexpr pointer data() const noexcept {
return s_.p; }
315 constexpr iterator begin() const noexcept {
return s_.p; }
317 constexpr iterator end() const noexcept {
return s_.p + s_.n; }
319 constexpr reverse_iterator rbegin() const noexcept {
320 return reverse_iterator(s_.p + s_.n);
323 constexpr reverse_iterator rend() const noexcept {
324 return reverse_iterator(s_.p);
327 constexpr const_iterator cbegin() const noexcept {
return s_.p; }
329 constexpr const_iterator cend() const noexcept {
return s_.p + s_.n; }
331 constexpr const_reverse_iterator crbegin() const noexcept {
332 return const_reverse_iterator(s_.p + s_.n);
335 constexpr const_reverse_iterator crend() const noexcept {
336 return const_reverse_iterator(s_.p);
340 detail::span_store<T, E> s_;
343#if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
344template <
class T, std::
size_t E>
constexpr std::size_t span<T, E>::extent;
347#ifdef __cpp_deduction_guides
348template <
class I,
class L> span(I *, L) -> span<I>;
350template <
class T, std::
size_t N> span(T (&)[N]) -> span<T, N>;
352template <
class T, std::
size_t N> span(std::array<T, N> &) -> span<T, N>;
354template <
class T, std::
size_t N>
355span(
const std::array<T, N> &) -> span<const T, N>;
357template <
class R> span(R &&) -> span<typename detail::span_data<R>::type>;
359template <
class T, std::
size_t E> span(span<T, E>) -> span<T, E>;
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());
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());
#define BOOST_CORE_DETAIL_ASSERT(expr)