13 #ifndef VC_COMMON_SPAN_H_ 14 #define VC_COMMON_SPAN_H_ 20 #include <type_traits> 21 #include "subscript.h" 23 namespace Vc_VERSIONED_NAMESPACE
25 #ifdef __cpp_inline_variables 28 constexpr ptrdiff_t dynamic_extent = -1;
31 template <
typename T, ptrdiff_t Extent = dynamic_extent>
class span;
33 template <
typename T, ptrdiff_t Extent>
34 constexpr
auto begin(
const span<T, Extent>& s) noexcept -> decltype(s.begin())
38 template <
typename T, ptrdiff_t Extent>
39 constexpr
auto end(
const span<T, Extent>& s) noexcept -> decltype(s.end())
44 template <
class T>
struct _is_span_impl :
public std::false_type {
47 template <
class T, ptrdiff_t Extent>
48 struct _is_span_impl<
span<T, Extent>> :
public std::true_type {
52 struct _is_span :
public _is_span_impl<typename std::remove_cv<T>::type> {
55 template <
class T>
struct _is_std_array_impl :
public std::false_type {
58 template <
class T,
size_t Sz>
59 struct _is_std_array_impl<array<T, Sz>> :
public std::true_type {
63 struct _is_std_array :
public _is_std_array_impl<typename std::remove_cv<T>::type> {
66 template <
class T,
class ElementType,
class =
void>
67 struct _is_span_compatible_container :
public std::false_type {
70 template <
class... Ts>
using _void_t = void;
72 template <
class C> constexpr
auto _std_data(C& c) -> decltype(c.data())
76 template <
class C> constexpr
auto _std_data(
const C& c) -> decltype(c.data())
80 template <
class T, std::
size_t N> constexpr T* _std_data(T (&array)[N]) noexcept
84 template <
class E> constexpr
const E* _std_data(std::initializer_list<E> il) noexcept
89 template <
class C> constexpr
auto _std_size(
const C& c) -> decltype(c.size())
93 template <
class T, std::
size_t N>
94 constexpr std::size_t _std_size(
const T (&array)[N]) noexcept
99 template <
class T,
class ElementType>
100 struct _is_span_compatible_container<
104 typename
std::enable_if<!_is_span<T>::value, std::nullptr_t>::type,
106 typename std::enable_if<!_is_std_array<T>::value, std::nullptr_t>::type,
108 typename std::enable_if<!std::is_array<T>::value, std::nullptr_t>::type,
110 decltype(data(std::declval<T>())), decltype(size(std::declval<T>())),
112 typename std::enable_if<
113 std::is_convertible<typename std::remove_pointer<decltype(
114 data(std::declval<T&>()))>::type (*)[],
115 ElementType (*)[]>::value,
116 std::nullptr_t>::type>> :
public std::true_type {
119 #if defined Vc_MSVC || (defined Vc_GCC && Vc_GCC < 0x50100) || defined Vc_ICC || !defined __cpp_constexpr || __cpp_constexpr < 201304 122 #define Vc_CONSTEXPR constexpr 125 template <
typename T, ptrdiff_t Extent>
class span 129 using element_type = T;
130 using value_type =
typename std::remove_cv<T>::type;
131 using index_type = ptrdiff_t;
132 using difference_type = ptrdiff_t;
134 using const_pointer =
const T*;
135 using reference = T&;
136 using const_reference =
const T&;
137 using iterator = pointer;
138 using const_iterator = const_pointer;
139 using reverse_iterator = std::reverse_iterator<iterator>;
140 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
142 static constexpr index_type extent = Extent;
143 static_assert(Extent >= 0,
"Can't have a span with an extent < 0");
146 Vc_CONSTEXPR
span() noexcept : data_{
nullptr}
148 static_assert(Extent == 0,
149 "Can't default construct a statically sized span with size > 0");
152 Vc_CONSTEXPR
span(
const span&) noexcept =
default;
153 Vc_CONSTEXPR
span& operator=(
const span&) noexcept =
default;
155 Vc_CONSTEXPR
span(pointer _ptr, index_type _count) : data_{_ptr}
158 Vc_ASSERT(((
void)
"size mismatch in span's constructor (ptr, len)", Extent == _count));
160 Vc_CONSTEXPR
span(pointer _f, pointer _l) : data_{_f}
163 Vc_ASSERT(((
void)
"size mismatch in span's constructor (ptr, ptr)",
164 Extent == distance(_f, _l)));
167 Vc_CONSTEXPR
span(element_type (&_arr)[Extent]) noexcept : data_{_arr} {}
168 Vc_CONSTEXPR
span(array<value_type, Extent>& _arr) noexcept : data_{_arr.data()} {}
169 Vc_CONSTEXPR
span(
const array<value_type, Extent>& _arr) noexcept : data_{_arr.data()} {}
171 template <
class Container>
172 inline Vc_CONSTEXPR
span(
174 typename std::enable_if<_is_span_compatible_container<Container, T>::value,
175 std::nullptr_t>::type =
nullptr)
176 : data_{_std_data(_c)}
178 Vc_ASSERT((
"size mismatch in span's constructor (container))",
179 Extent == _std_size(_c)));
182 template <
class Container>
183 inline Vc_CONSTEXPR
span(
185 typename std::enable_if<_is_span_compatible_container<const Container, T>::value,
186 std::nullptr_t>::type =
nullptr)
187 : data_{_std_data(_c)}
189 Vc_ASSERT((
"size mismatch in span's constructor (const container)",
190 Extent == _std_size(_c)));
193 template <
class OtherElementType>
194 inline Vc_CONSTEXPR
span(
195 const span<OtherElementType, Extent>& _other,
196 typename std::enable_if<
197 std::is_convertible<OtherElementType (*)[], element_type (*)[]>::value,
198 std::nullptr_t>::type =
nullptr)
199 : data_{_other.data()}
203 template <
class OtherElementType>
204 inline Vc_CONSTEXPR
span(
205 const span<OtherElementType, dynamic_extent>& _other,
206 typename std::enable_if<
207 std::is_convertible<OtherElementType (*)[], element_type (*)[]>::value,
208 std::nullptr_t>::type =
nullptr) noexcept
209 : data_{_other.data()}
211 Vc_ASSERT((
"size mismatch in span's constructor (other span)",
212 Extent == _other.size()));
217 template <ptrdiff_t Count>
218 inline Vc_CONSTEXPR span<element_type, Count> first() const noexcept
220 static_assert(Count >= 0,
"Count must be >= 0 in span::first()");
221 static_assert(Count <= Extent,
"Count out of range in span::first()");
222 return {data(), Count};
225 template <ptrdiff_t Count>
226 inline Vc_CONSTEXPR span<element_type, Count> last() const noexcept
228 static_assert(Count >= 0,
"Count must be >= 0 in span::last()");
229 static_assert(Count <= Extent,
"Count out of range in span::last()");
230 return {data() + size() - Count, Count};
233 Vc_CONSTEXPR span<element_type, dynamic_extent> first(index_type _count)
const noexcept
235 Vc_ASSERT((
"Count out of range in span::first(count)",
236 _count >= 0 && _count <= size()));
237 return {data(), _count};
240 Vc_CONSTEXPR span<element_type, dynamic_extent> last(index_type _count)
const noexcept
243 (
"Count out of range in span::last(count)", _count >= 0 && _count <= size()));
244 return {data() + size() - _count, _count};
251 template <ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent>
252 inline Vc_CONSTEXPR
auto subspan() const noexcept
253 -> span<element_type, Count != dynamic_extent ? Count : Extent - Offset>
256 (
"Offset out of range in span::subspan()", Offset >= 0 && Offset <= size()));
257 return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
260 inline Vc_CONSTEXPR span<element_type, dynamic_extent> subspan(
261 index_type offset, index_type count = dynamic_extent)
const noexcept
263 Vc_ASSERT((
"Offset out of range in span::subspan(offset, count)",
264 offset >= 0 && offset <= size()));
265 Vc_ASSERT((
"Count out of range in span::subspan(offset, count)",
266 (count >= 0 && count <= size()) || count == dynamic_extent));
267 if (count == dynamic_extent) {
268 return {data() + offset, size() - offset};
270 Vc_ASSERT((
"count + offset out of range in span::subspan(offset, count)",
271 offset + count <= size()));
272 return {data() + offset, count};
276 Vc_CONSTEXPR index_type size() const noexcept {
return Extent; }
277 Vc_CONSTEXPR index_type size_bytes() const noexcept
279 return Extent *
sizeof(element_type);
281 Vc_CONSTEXPR
bool empty() const noexcept {
return Extent == 0; }
283 Vc_CONSTEXPR reference operator[](index_type _idx)
const noexcept
285 Vc_ASSERT((
"span<T,N>[] index out of bounds", _idx >= 0 && _idx < size()));
289 Vc_CONSTEXPR reference operator()(index_type _idx)
const noexcept
291 Vc_ASSERT((
"span<T,N>() index out of bounds", _idx >= 0 && _idx < size()));
295 Vc_CONSTEXPR pointer data() const noexcept {
return data_; }
298 Vc_CONSTEXPR iterator begin() const noexcept {
return iterator(data()); }
299 Vc_CONSTEXPR iterator end() const noexcept {
return iterator(data() + size()); }
300 Vc_CONSTEXPR const_iterator cbegin() const noexcept {
return const_iterator(data()); }
301 Vc_CONSTEXPR const_iterator cend() const noexcept
303 return const_iterator(data() + size());
305 Vc_CONSTEXPR reverse_iterator rbegin() const noexcept {
return reverse_iterator(end()); }
306 Vc_CONSTEXPR reverse_iterator rend() const noexcept {
return reverse_iterator(begin()); }
307 Vc_CONSTEXPR const_reverse_iterator crbegin() const noexcept
309 return const_reverse_iterator(cend());
311 Vc_CONSTEXPR const_reverse_iterator crend() const noexcept
313 return const_reverse_iterator(cbegin());
316 Vc_CONSTEXPR
void swap(span& _other) noexcept
319 data_ = _other.data_;
323 #ifdef __cpp_lib_byte 324 span<const std::byte, Extent * sizeof(element_type)> _as_bytes() const noexcept
326 return {
reinterpret_cast<const std::byte*
>(data()), size_bytes()};
329 span<std::byte, Extent * sizeof(element_type)> _as_writeable_bytes() const noexcept
331 return {
reinterpret_cast<std::byte*
>(data()), size_bytes()};
333 #endif // __cpp_lib_byte 339 template <
typename T>
class span<T, dynamic_extent>
344 using element_type = T;
345 using value_type =
typename std::remove_cv<T>::type;
346 using index_type = ptrdiff_t;
347 using difference_type = ptrdiff_t;
349 using const_pointer =
const T*;
350 using reference = T&;
351 using const_reference =
const T&;
352 using iterator = pointer;
353 using const_iterator = const_pointer;
354 using reverse_iterator = std::reverse_iterator<iterator>;
355 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
357 static constexpr index_type extent = dynamic_extent;
360 Vc_CONSTEXPR
span() noexcept : data_{
nullptr}, size_{0} {}
362 Vc_CONSTEXPR
span(
const span&) noexcept =
default;
363 Vc_CONSTEXPR span& operator=(
const span&) noexcept =
default;
365 Vc_CONSTEXPR
span(pointer _ptr, index_type _count) : data_{_ptr}, size_{_count} {}
366 Vc_CONSTEXPR
span(pointer _f, pointer _l) : data_{_f}, size_{distance(_f, _l)} {}
369 inline Vc_CONSTEXPR
span(element_type (&_arr)[Sz]) noexcept : data_{_arr}, size_{Sz}
374 inline Vc_CONSTEXPR
span(array<value_type, Sz>& _arr) noexcept
375 : data_{_arr.data()}, size_{Sz}
380 inline Vc_CONSTEXPR
span(
const array<value_type, Sz>& _arr) noexcept
381 : data_{_arr.data()}, size_{Sz}
385 template <
class Container>
386 inline Vc_CONSTEXPR
span(
388 typename std::enable_if<_is_span_compatible_container<Container, T>::value,
389 std::nullptr_t>::type =
nullptr)
390 : data_{_std_data(_c)}, size_{index_type(_std_size(_c))}
394 template <
class Container>
395 inline Vc_CONSTEXPR
span(
397 typename std::enable_if<_is_span_compatible_container<const Container, T>::value,
398 std::nullptr_t>::type =
nullptr)
399 : data_{_std_data(_c)}, size_{index_type(_std_size(_c))}
403 template <
class OtherElementType, ptrdiff_t OtherExtent>
404 inline Vc_CONSTEXPR
span(
405 const span<OtherElementType, OtherExtent>& _other,
406 typename std::enable_if<
407 std::is_convertible<OtherElementType (*)[], element_type (*)[]>::value,
408 std::nullptr_t>::type =
nullptr) noexcept
409 : data_{_other.data()}, size_{_other.size()}
415 template <ptrdiff_t Count>
416 inline Vc_CONSTEXPR span<element_type, Count> first() const noexcept
418 static_assert(Count >= 0,
"");
419 Vc_ASSERT((
"Count out of range in span::first()", Count <= size()));
420 return {data(), Count};
423 template <ptrdiff_t Count>
424 inline Vc_CONSTEXPR span<element_type, Count> last() const noexcept
426 static_assert(Count >= 0,
"");
427 Vc_ASSERT((
"Count out of range in span::last()", Count <= size()));
428 return {data() + size() - Count, Count};
431 Vc_CONSTEXPR span<element_type, dynamic_extent> first(index_type _count)
const noexcept
433 Vc_ASSERT((
"Count out of range in span::first(count)",
434 _count >= 0 && _count <= size()));
435 return {data(), _count};
438 Vc_CONSTEXPR span<element_type, dynamic_extent> last(index_type _count)
const noexcept
441 (
"Count out of range in span::last(count)", _count >= 0 && _count <= size()));
442 return {data() + size() - _count, _count};
445 template <ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent>
446 inline Vc_CONSTEXPR span<T, dynamic_extent> subspan() const noexcept
449 (
"Offset out of range in span::subspan()", Offset >= 0 && Offset <= size()));
450 Vc_ASSERT((
"Count out of range in span::subspan()",
451 Count == dynamic_extent || Offset + Count <= size()));
452 return {data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
455 Vc_CONSTEXPR span<element_type, dynamic_extent>
inline subspan(
456 index_type _offset, index_type _count = dynamic_extent)
const noexcept
458 Vc_ASSERT((
"Offset out of range in span::subspan(offset, count)",
459 _offset >= 0 && _offset <= size()));
460 Vc_ASSERT((
"count out of range in span::subspan(offset, count)",
461 (_count >= 0 && _count <= size()) || _count == dynamic_extent));
462 if (_count == dynamic_extent)
463 return {data() + _offset, size() - _offset};
464 Vc_ASSERT((
"Offset + count out of range in span::subspan(offset, count)",
465 _offset + _count <= size()));
466 return {data() + _offset, _count};
469 Vc_CONSTEXPR index_type size() const noexcept {
return size_; }
470 Vc_CONSTEXPR index_type size_bytes() const noexcept
472 return size_ *
sizeof(element_type);
474 Vc_CONSTEXPR
bool empty() const noexcept {
return size_ == 0; }
476 Vc_CONSTEXPR reference operator[](index_type _idx)
const noexcept
478 Vc_ASSERT((
"span<T>[] index out of bounds", _idx >= 0 && _idx < size()));
482 Vc_CONSTEXPR reference operator()(index_type _idx)
const noexcept
484 Vc_ASSERT((
"span<T>() index out of bounds", _idx >= 0 && _idx < size()));
488 Vc_CONSTEXPR pointer data() const noexcept {
return data_; }
491 Vc_CONSTEXPR iterator begin() const noexcept {
return iterator(data()); }
492 Vc_CONSTEXPR iterator end() const noexcept {
return iterator(data() + size()); }
493 Vc_CONSTEXPR const_iterator cbegin() const noexcept {
return const_iterator(data()); }
494 Vc_CONSTEXPR const_iterator cend() const noexcept
496 return const_iterator(data() + size());
498 Vc_CONSTEXPR reverse_iterator rbegin() const noexcept {
return reverse_iterator(end()); }
499 Vc_CONSTEXPR reverse_iterator rend() const noexcept {
return reverse_iterator(begin()); }
500 Vc_CONSTEXPR const_reverse_iterator crbegin() const noexcept
502 return const_reverse_iterator(cend());
504 Vc_CONSTEXPR const_reverse_iterator crend() const noexcept
506 return const_reverse_iterator(cbegin());
509 Vc_CONSTEXPR
void swap(span& _other) noexcept
512 data_ = _other.data_;
515 index_type _sz = size_;
516 size_ = _other.size_;
520 #ifdef __cpp_lib_byte 521 span<const std::byte, dynamic_extent> _as_bytes() const noexcept
523 return {
reinterpret_cast<const std::byte*
>(data()), size_bytes()};
526 span<std::byte, dynamic_extent> _as_writeable_bytes() const noexcept
528 return {
reinterpret_cast<std::byte*
>(data()), size_bytes()};
530 #endif // __cpp_lib_byte 537 template <
class T1, ptrdiff_t Extent1,
class T2, ptrdiff_t Extent2>
538 Vc_CONSTEXPR
bool operator==(
const span<T1, Extent1>& lhs,
const span<T2, Extent2>& rhs)
540 return equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
543 template <
class T1, ptrdiff_t Extent1,
class T2, ptrdiff_t Extent2>
544 Vc_CONSTEXPR
bool operator!=(
const span<T1, Extent1>& lhs,
const span<T2, Extent2>& rhs)
546 return !(rhs == lhs);
549 template <
class T1, ptrdiff_t Extent1,
class T2, ptrdiff_t Extent2>
550 Vc_CONSTEXPR
bool operator<(const span<T1, Extent1>& lhs,
const span<T2, Extent2>& rhs)
552 return lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
555 template <
class T1, ptrdiff_t Extent1,
class T2, ptrdiff_t Extent2>
556 Vc_CONSTEXPR
bool operator<=(const span<T1, Extent1>& lhs,
const span<T2, Extent2>& rhs)
561 template <
class T1, ptrdiff_t Extent1,
class T2, ptrdiff_t Extent2>
562 Vc_CONSTEXPR
bool operator>(
const span<T1, Extent1>& lhs,
const span<T2, Extent2>& rhs)
567 template <
class T1, ptrdiff_t Extent1,
class T2, ptrdiff_t Extent2>
568 Vc_CONSTEXPR
bool operator>=(
const span<T1, Extent1>& lhs,
const span<T2, Extent2>& rhs)
574 template <
class T, ptrdiff_t Extent>
575 auto as_bytes(span<T, Extent> _s) noexcept -> decltype(_s._as_bytes())
577 return _s._as_bytes();
580 template <
class T, ptrdiff_t Extent>
581 auto as_writeable_bytes(span<T, Extent> _s) noexcept ->
582 typename std::enable_if<!std::is_const<T>::value,
583 decltype(_s._as_writeable_bytes())>::type
585 return _s._as_writeable_bytes();
588 template <
class T, ptrdiff_t Extent>
589 Vc_CONSTEXPR
void swap(span<T, Extent>& lhs, span<T, Extent>& rhs) noexcept
597 #ifdef __cpp_deduction_guides 598 template <
class T,
size_t Sz>
span(T (&)[Sz])->span<T, Sz>;
600 template <
class T,
size_t Sz>
span(array<T, Sz>&)->span<T, Sz>;
602 template <
class T,
size_t Sz>
span(
const array<T, Sz>&)->span<
const T, Sz>;
604 template <
class Container>
span(Container&)->span<
typename Container::value_type>;
606 template <
class Container>
607 span(
const Container&)->span<
const typename Container::value_type>;
608 #endif // __cpp_deduction_guides 634 template <
typename T, ptrdiff_t Extent = dynamic_extent>
635 using span = Common::AdaptSubscriptOperator<Common::span<T, Extent>>;
639 template <
typename T, ptrdiff_t Extent>
640 struct has_contiguous_storage_impl<Vc::span<T, Extent>> :
public std::true_type {
642 template <
typename T, ptrdiff_t Extent>
643 struct has_contiguous_storage_impl<Vc::
Common::span<T, Extent>> :
public std::true_type {
649 #endif // VC_COMMON_SPAN_H_ void swap(Adapter< S, T, N > &a, std::size_t i, S &x)
Swaps one scalar object x with a SIMD slot at offset i in the simdized object a.
result_vector_type< L, R >::mask_type operator!=(L &&lhs, R &&rhs)
Applies != component-wise and concurrently.
result_vector_type< L, R >::mask_type operator==(L &&lhs, R &&rhs)
Applies == component-wise and concurrently.
result_vector_type< L, R >::mask_type operator>=(L &&lhs, R &&rhs)
Applies >= component-wise and concurrently.
result_vector_type< L, R >::mask_type operator>(L &&lhs, R &&rhs)
Applies > component-wise and concurrently.
Common::AdaptSubscriptOperator< Common::span< T, Extent > > span
An adapted std::span with additional subscript operators supporting gather and scatter operations...