8#ifndef BOOST_CORE_SPAN_HPP
9#define BOOST_CORE_SPAN_HPP
20template<
class T, std::
size_t E = dynamic_extent>
25template<
class U,
class T>
26struct span_convertible {
27 static constexpr bool value = std::is_convertible<U(*)[], T(*)[]>::value;
30template<std::
size_t E, std::
size_t N>
35template<
class T, std::
size_t E,
class U, std::
size_t N>
36struct span_compatible {
37 static constexpr bool value = span_capacity<E, N>::value &&
38 span_convertible<U, T>::value;
42using span_uncvref =
typename std::remove_cv<
typename
43 std::remove_reference<T>::type>::type;
47 static constexpr bool value =
false;
50template<
class T, std::
size_t E>
51struct span_is_span<boost::span<T, E> > {
52 static constexpr bool value =
true;
57 static constexpr bool value =
false;
60template<
class T, std::
size_t N>
61struct span_is_array<std::array<T, N> > {
62 static constexpr bool value =
true;
66using span_ptr =
decltype(
boost::data(std::declval<T&>()));
68template<
class,
class =
void>
73 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>
79 static constexpr bool value =
false;
82template<
class R,
class T>
83struct span_has_data<R, T, typename std::enable_if<span_convertible<typename
84 span_data<R>::type, T>::value>::type> {
85 static constexpr bool value =
true;
88template<
class,
class =
void>
90 static constexpr bool value =
false;
94struct span_has_size<R, typename
95 std::enable_if<std::is_convertible<decltype(std::declval<R&>().size()),
96 std::size_t>::value>::type> {
97 static constexpr bool value =
true;
100template<
class R,
class T>
101struct span_is_range {
102 static constexpr bool value = (std::is_const<T>::value ||
103 std::is_lvalue_reference<R>::value) &&
104 !span_is_span<span_uncvref<R> >::value &&
105 !span_is_array<span_uncvref<R> >::value &&
106 !std::is_array<span_uncvref<R> >::value &&
107 span_has_data<R, T>::value &&
108 span_has_size<R>::value;
111template<std::
size_t E, std::
size_t N>
112struct span_implicit {
117template<
class T, std::
size_t E,
class U, std::
size_t N>
118struct span_copyable {
120 span_capacity<E, N>::value) && span_convertible<U, T>::value;
123template<std::
size_t E, std::
size_t O>
129template<
class T, std::
size_t E>
131 constexpr span_store(T* p_, std::size_t) noexcept
133 static constexpr std::size_t n = E;
139 constexpr span_store(T* p_, std::size_t n_) noexcept
146template<
class T, std::
size_t E>
148 static constexpr std::size_t value =
sizeof(T) * E;
158template<
class T, std::
size_t E>
161 typedef T element_type;
162 typedef typename std::remove_cv<T>::type value_type;
163 typedef std::size_t size_type;
164 typedef std::ptrdiff_t difference_type;
166 typedef const T* const_pointer;
167 typedef T& reference;
168 typedef const T& const_reference;
170 typedef const T* const_iterator;
171 typedef std::reverse_iterator<T*> reverse_iterator;
172 typedef std::reverse_iterator<const T*> const_reverse_iterator;
174 static constexpr std::size_t extent = E;
176 template<std::size_t N = E,
177 typename std::enable_if<N == dynamic_extent || N == 0, int>::type = 0>
178 constexpr span() noexcept
183 detail::span_convertible<I, T>::value,
int>::type = 0>
184 constexpr span(I* f, size_type c)
189 detail::span_convertible<I, T>::value,
int>::type = 0>
190 explicit constexpr span(I* f, size_type c)
193 template<
class I,
class L,
195 detail::span_convertible<I, T>::value,
int>::type = 0>
196 constexpr span(I* f, L* l)
199 template<
class I,
class L,
201 detail::span_convertible<I, T>::value,
int>::type = 0>
202 explicit constexpr span(I* f, L* l)
205 template<std::size_t N,
206 typename std::enable_if<detail::span_capacity<E, N>::value,
208 constexpr span(
typename std::enable_if<true, T>::type (&a)[N]) noexcept
211 template<
class U, std::size_t N,
212 typename std::enable_if<detail::span_compatible<T, E, U, N>::value,
214 constexpr span(std::array<U, N>& a) noexcept
215 : s_(a.data(), N) { }
217 template<
class U, std::size_t N,
218 typename std::enable_if<detail::span_compatible<T, E,
const U,
219 N>::value,
int>::type = 0>
220 constexpr span(
const std::array<U, N>& a) noexcept
221 : s_(a.data(), N) { }
225 detail::span_is_range<R, T>::value,
int>::type = 0>
226 constexpr span(R&& r)
noexcept(
noexcept(
boost::data(r)) &&
232 detail::span_is_range<R, T>::value,
int>::type = 0>
233 explicit constexpr span(R&& r)
noexcept(
noexcept(
boost::data(r)) &&
237 template<
class U, std::size_t N,
238 typename std::enable_if<detail::span_implicit<E, N>::value &&
239 detail::span_copyable<T, E, U, N>::value,
int>::type = 0>
240 constexpr span(
const span<U, N>& s) noexcept
241 : s_(s.data(), s.size()) { }
243 template<
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,
int>::type = 0>
246 explicit constexpr span(
const span<U, N>& s) noexcept
247 : s_(s.data(), s.size()) { }
249 template<std::
size_t C>
250 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>
256 constexpr span<T, C> last()
const {
257 static_assert(C <= E,
"Count <= Extent");
258 return span<T, C>(s_.p + (s_.n - C), C);
261 template<std::
size_t O, std::
size_t C = dynamic_extent>
263 span<T, detail::span_sub<E, O>::value> >::type subspan()
const {
264 static_assert(O <= E,
"Offset <= Extent");
265 return span<T, detail::span_sub<E, O>::value>(s_.p + O, s_.n - O);
268 template<std::
size_t O, std::
size_t C = dynamic_extent>
270 span<T, C> >::type subspan()
const {
271 static_assert(O <= E && C <= E - O,
272 "Offset <= Extent && Count <= Extent - Offset");
273 return span<T, C>(s_.p + O, C);
276 constexpr span<T, dynamic_extent> first(size_type c)
const {
277 return span<T, dynamic_extent>(s_.p, c);
280 constexpr span<T, dynamic_extent> last(size_type c)
const {
281 return span<T, dynamic_extent>(s_.p + (s_.n - c), c);
284 constexpr span<T, dynamic_extent> subspan(size_type o,
286 return span<T, dynamic_extent>(s_.p + o,
290 constexpr size_type size() const noexcept {
294 constexpr size_type size_bytes() const noexcept {
295 return s_.n *
sizeof(T);
298 constexpr bool empty() const noexcept {
302 constexpr reference operator[](size_type i)
const {
306 constexpr reference front()
const {
310 constexpr reference back()
const {
311 return s_.p[s_.n - 1];
314 constexpr pointer data() const noexcept {
318 constexpr iterator begin() const noexcept {
322 constexpr iterator end() const noexcept {
326 constexpr reverse_iterator rbegin() const noexcept {
327 return reverse_iterator(s_.p + s_.n);
330 constexpr reverse_iterator rend() const noexcept {
331 return reverse_iterator(s_.p);
334 constexpr const_iterator cbegin() const noexcept {
338 constexpr const_iterator cend() const noexcept {
342 constexpr const_reverse_iterator crbegin() const noexcept {
343 return const_reverse_iterator(s_.p + s_.n);
346 constexpr const_reverse_iterator crend() const noexcept {
347 return const_reverse_iterator(s_.p);
351 detail::span_store<T, E> s_;
354template<
class T, std::
size_t E>
355constexpr std::size_t span<T, E>::extent;
357#ifdef __cpp_deduction_guides
358template<
class I,
class L>
359span(I*, L) -> span<I>;
361template<
class T, std::
size_t N>
362span(T(&)[N]) -> span<T, N>;
364template<
class T, std::
size_t N>
365span(std::array<T, N>&) -> span<T, N>;
367template<
class T, std::
size_t N>
368span(
const std::array<T, N>&) -> span<const T, N>;
371span(R&&) -> span<typename detail::span_data<R>::type>;
373template<
class T, std::
size_t E>
374span(span<T, E>) -> span<T, E>;
378template<
class T, std::
size_t E>
379inline span<const std::byte, detail::span_bytes<T, E>::value>
380as_bytes(span<T, E> s)
noexcept
382 return span<
const std::byte, detail::span_bytes<T,
383 E>::value>(
reinterpret_cast<const std::byte*
>(s.data()),
387template<
class T, std::
size_t E>
388inline typename std::enable_if<!std::is_const<T>::value,
389 span<std::byte, detail::span_bytes<T, E>::value> >::type
390as_writable_bytes(span<T, E> s)
noexcept
392 return span<std::byte, detail::span_bytes<T,
393 E>::value>(
reinterpret_cast<std::byte*
>(s.data()), s.size_bytes());
constexpr std::size_t dynamic_extent
constexpr auto data(C &c) noexcept(noexcept(c.data())) -> decltype(c.data())