35 #ifndef KAT_CONTAINERS_SPAN_HPP_    36 #define KAT_CONTAINERS_SPAN_HPP_    38 #include <type_traits>    43 #include "detail/normal_iterator.hpp"    44 #include <kat/detail/execution_space_specifiers.hpp>    45 #include <kat/detail/range_access.hpp>    48 #if __cplusplus >= 202001L    54 #if __cplusplus >= 201703L    57 constexpr 
const std::size_t dynamic_extent = 
static_cast<std::size_t
>(-1);
    59 template<
typename Type, std::
size_t Extent>
    65 #if __cplusplus >= 202001L    66 using iter_reference_t = std::iter_reference_t<T>;
    68 using iter_reference_t = decltype(*std::declval<T&>());
    74 template<
typename T, std::
size_t Num>
    77 #if __cplusplus >= 202001L    78 template<
typename T, std::
size_t Num>
    79 struct is_span<std::
span<T, Num>> : std::true_type {};
    81 template<
typename T, std::
size_t Num>
    82 struct is_span<std::
span<T, Num>> : std::true_type {};
    96 template<std::
size_t Extent>
   103     static constexpr KAT_HD std::size_t extent() noexcept
   113     : extent_value(extent)
   116     constexpr KAT_HD std::size_t
   117     extent() 
const noexcept
   119         return this->extent_value;
   123     std::size_t extent_value;
   128 template<
typename Type, std::
size_t Extent = dynamic_extent>
   134     template<std::size_t Offset, std::size_t Count, typename = typename std::enable_if<Count != dynamic_extent>::type>
   135     static constexpr KAT_HD std::size_t S_subspan_extent()
   137         static_assert(Count != dynamic_extent, 
"This implementation should not have been instantiated for Count == dynamic_extent...");
   141     template<std::
size_t Offset>
   142     static constexpr KAT_HD std::size_t S_subspan_extent<Offset, dynamic_extent>()
   144     #if __cplusplus >= 201703L   145         if constexpr KAT_HD (extent != dynamic_extent)
   147         if (extent != dynamic_extent)
   149             return Extent - Offset;
   151             return dynamic_extent;
   161       template<
typename T, std::
size_t ArrayExtent>
   162     using is_compatible_array = std::integral_constant<bool,
   164       and (Extent == dynamic_extent or ArrayExtent == Extent)
   165       and (std::is_const<Type>::value or not std::is_const<T>::value)
   167       and __is_array_convertible<Type, T>
   171     template<
typename Iter, 
typename Ref = detail::iter_reference_t<Iter>>
   172     using is_compatible_iterator = std::integral_constant<bool,
   174 #if __cplusplus >= 202001L   176         and contiguous_iterator<Iter>::value  
   178         and std::is_lvalue_reference<detail::iter_reference_t<Iter>>::value,
   179         and std::is_same<std::iter_value_t<Iter>, std::remove_cvref_t<Ref>>::value,
   182         and __is_array_convertible<Type, std::remove_reference_t<Ref>>::value
   186 #if __cplusplus >= 202001L   187     template<
typename Range>
   188     using __is_compatible_range
   189       = is_compatible_iterator<ranges::iterator_t<Range>>;
   194     using value_type             = 
typename std::remove_cv<Type>::type;
   195     using element_type           = Type;
   196     using size_type              = std::size_t;
   197     using reference              = element_type&;
   198     using const_reference        = 
const element_type&;
   199     using pointer                = Type*;
   200     using const_pointer          = 
const Type*;
   202     using iterator               = kat::detail::normal_iterator<pointer, span>;
   203     using const_iterator         = kat::detail::normal_iterator<const_pointer, span>;
   204     using reverse_iterator       = std::reverse_iterator<iterator>;
   205     using const_reverse_iterator = std::reverse_iterator<const_iterator>;
   206     using difference_type        = std::ptrdiff_t;
   209 #if __cplusplus >= 201703L   212     static constexpr 
const std::size_t extent = Extent;
   216     constexpr KAT_HD 
span() noexcept
   217 #if __cplusplus >= 202001L   218     requires ((Extent + 1u) <= 1u)
   220     : extent_(0), ptr_(
nullptr)
   222 #if __cplusplus < 202001L   223         static_assert((Extent + 1u) <= 1u, 
"Invalid Extent value - for this constructor, can be either dynamic_extent or 0");
   228     span(
const span&) noexcept = 
default;
   230 #if __cplusplus >= 202001L   231     template<
typename T, std::
size_t ArrayExtent>
   232     requires (is_compatible_array<T, ArrayExtent>::value)
   234     template<typename T, std::size_t ArrayExtent, typename = typename std::enable_if<is_compatible_array<T, ArrayExtent>::value>::type >
   237     span(T (&arr)[ArrayExtent]) noexcept
   238     : 
span(static_cast<pointer>(arr), ArrayExtent)
   241         static_assert(is_compatible_array<T, ArrayExtent>::value, 
"Attempt to construct a span with an incompatible raw array");
   244 #if __cplusplus >= 202001L   245     template<
typename T, std::
size_t ArrayExtent>
   246     requires (is_compatible_array<T, ArrayExtent>::value)
   248     template<typename T, std::size_t ArrayExtent, typename = typename std::enable_if<is_compatible_array<T, ArrayExtent>::value>::type >
   252     : 
span(static_cast<pointer>(arr.data()), ArrayExtent)
   254         static_assert(is_compatible_array<T, ArrayExtent>::value, 
"Attempt to construct a span with an incompatible kat::array");
   257 #if __cplusplus >= 202001L   258     template<
typename T, std::
size_t ArrayExtent>
   259     requires (is_compatible_array<T, ArrayExtent>::value)
   261     template<typename T, std::size_t ArrayExtent, typename = typename std::enable_if<is_compatible_array<const T, ArrayExtent>::value>::type >
   264     : 
span(static_cast<pointer>(arr.data()), ArrayExtent)
   266         static_assert(is_compatible_array<T, ArrayExtent>::value, 
"Attempt to construct a span with an incompatible const kat::array");
   269 #if __cplusplus >= 202001L   270     template<
typename T, std::
size_t ArrayExtent>
   271     requires (is_compatible_array<T, ArrayExtent>::value)
   273     template<typename T, std::size_t ArrayExtent, typename = typename std::enable_if<is_compatible_array<T, ArrayExtent>::value>::type >
   275     constexpr KAT_HOST 
span(std::array<T, ArrayExtent>& arr) noexcept
   276     : 
span(static_cast<pointer>(arr.data()), ArrayExtent)
   278         static_assert(is_compatible_array<T, ArrayExtent>::value, 
"Constructing a span with an incompatible std::array");
   281 #if __cplusplus >= 202001L   282     template<
typename T, std::
size_t ArrayExtent>
   283     requires (is_compatible_array<T, ArrayExtent>::value)
   285     template<typename T, std::size_t ArrayExtent, typename = typename std::enable_if<is_compatible_array<const T, ArrayExtent>::value>::type >
   287     constexpr KAT_HOST 
span(
const std::array<T, ArrayExtent>& arr) noexcept
   288     : 
span(static_cast<pointer>(arr.data()), ArrayExtent)
   290         static_assert(is_compatible_array<T, ArrayExtent>::value, 
"Constructing a span with an incompatible const std::array");
   298 #if __cplusplus >= 202001L   299     template<ranges::contiguous_range Range>
   300     requires (Extent == dynamic_extent)
   302       and (!detail::__is_std_array<std::remove_cvref_t<Range>>::value)
   303       and (!is_array_v<std::remove_reference_t<Range>>)
   304       and (__is_compatible_range<Range>::value)
   307     noexcept(noexcept(ranges::data(range))
   308           and noexcept(ranges::size(range)))
   309     : 
span(ranges::data(range), ranges::size(range))
   315 #if __cplusplus >= 202001L   316     template<contiguous_iterator ContiguousIterator,
   317     sized_sentinel_for<ContiguousIterator> Sentinel>
   318       requires (is_compatible_iterator<ContiguousIterator>::value)
   319         and (!is_convertible_v<Sentinel, size_type>)
   321     span(ContiguousIterator first, Sentinel last)
   322     noexcept(noexcept(last - first))
   323     : extent_(static_cast<size_type>(last - first)),
   324       ptr_(std::to_address(first))
   326       if (Extent != dynamic_extent)
   327         assert((last - first) == Extent);
   330     constexpr KAT_HD 
span(pointer first, pointer last) noexcept
   331         : extent_(static_cast<size_type>(last - first)),
   336 #if __cplusplus >= 202001L   337     template<contiguous_iterator ContiguousIterator>
   338     requires (is_compatible_iterator<ContiguousIterator>::value)
   340     span(ContiguousIterator first, size_type count)
   342     : extent_(count), ptr_(std::to_address(first))
   343     { assert(Extent == dynamic_extent or count == Extent); }
   345     constexpr KAT_HD 
span(pointer first, std::size_t count) noexcept
   346         : extent_(count), ptr_(first)
   351       template<
typename OType, std::
size_t OExtent>
   352 #if __cplusplus >= 2017031L   353     requires (Extent == dynamic_extent or Extent == OExtent)
   354       and (__is_array_convertible<Type, OType>::value)
   358     : extent_(s.size()), ptr_(s.data())
   360 #if __cplusplus < 2017031L   361         static_assert(Extent == dynamic_extent or Extent == OExtent, 
"Invalid extent");
   368     constexpr KAT_HD 
span&
   369     operator=(
const span&) noexcept = 
default;
   373     constexpr KAT_HD size_type
   374     size() 
const noexcept
   375     {   
return extent_.extent();}
   377     constexpr KAT_HD size_type
   378     size_bytes() 
const noexcept
   379     {   
return extent_.extent() * 
sizeof(element_type);}
   381     [[nodiscard]] constexpr KAT_HD 
bool   382     empty() 
const noexcept
   383     {   
return size() == 0;}
   387     constexpr KAT_HD reference
   388     front() 
const noexcept
   390         static_assert(extent != 0, 
"Zero span extent");
   395     constexpr KAT_HD reference
   396     back() 
const noexcept
   398         static_assert(extent != 0, 
"Zero span extent");
   400         return *(ptr_ + (size() - 1));
   403     constexpr KAT_HD reference
   404     operator[](size_type idx) 
const noexcept
   406         static_assert(extent != 0, 
"Zero span extent");
   407         assert(idx < size());
   408         return *(ptr_ + idx);
   411     constexpr KAT_HD pointer
   412     data() 
const noexcept
   417     constexpr KAT_HD iterator
   418     begin() 
const noexcept
   419     {   
return iterator(ptr_);}
   421     constexpr KAT_HD const_iterator
   422     cbegin() 
const noexcept
   423     {   
return const_iterator(ptr_);}
   425     constexpr KAT_HD iterator
   427     {   
return iterator(ptr_ + size());}
   429     constexpr KAT_HD const_iterator
   430     cend() 
const noexcept
   431     {   
return const_iterator(ptr_ + size());}
   433     constexpr KAT_HD reverse_iterator
   434     rbegin() 
const noexcept
   435     {   
return reverse_iterator(this->end());}
   437     constexpr KAT_HD const_reverse_iterator
   438     crbegin() 
const noexcept
   439     {   
return const_reverse_iterator(this->cend());}
   441     constexpr KAT_HD reverse_iterator
   442     rend() 
const noexcept
   443     {   
return reverse_iterator(this->begin());}
   445     constexpr KAT_HD const_reverse_iterator
   446     crend() 
const noexcept
   447     {   
return const_reverse_iterator(this->cbegin());}
   451     template<std::
size_t Count>
   453     first() 
const noexcept
   455     #if __cplusplus >= 201703L   456         if constexpr KAT_HD (Extent == dynamic_extent)
   457         assert(Count <= size());
   459         static_assert(Count <= extent);
   461         if (Extent == dynamic_extent) {
   462             assert ((Count < size() or Count == size()) and 
"Span fixed element count exceeds its size");
   465             assert ((size() < Extent or size() == Extent ) and 
"Span size exceeds its extent");
   468         return { data(), Count };
   472     first(size_type count) 
const noexcept
   474         assert(count <= size());
   475         return { data(), count };
   478     template<std::
size_t Count>
   480     last() 
const noexcept
   482     #if __cplusplus >= 201703L   483         if constexpr KAT_HD (Extent == dynamic_extent)
   484         assert(Count <= size());
   486         static_assert(Count <= extent);
   488         if (Extent == dynamic_extent) {
   489             assert ((Count < size() or Count == size()) and 
"Span fixed element count exceeds its size");
   492             assert ((size() < Extent  or size() == Extent) and 
"Span size exceeds its extent");
   495         return {data() + (size() - Count), Count};
   499     last(size_type count) 
const noexcept
   501         assert(count <= size());
   502         return {data() + (size() - count), count};
   505     template<std::
size_t Offset, std::
size_t Count = dynamic_extent>
   506     constexpr KAT_HD 
auto   507     subspan() 
const noexcept
   510     #if __cplusplus >= 201703L   511         if constexpr KAT_HD (Extent == dynamic_extent)
   512         assert(Offset <= size());
   514         static_assert(Offset <= extent);
   516         if (Extent == dynamic_extent) {
   517             assert((Offset < size() or Offset == size()) and 
"Subspan offset exceeds span size");
   520             assert((Offset < Extent or Offset == Extent) and 
"Subspan offset exceeds fixed span extent");
   524     #if __cplusplus >= 201703L   525         if constexpr KAT_HD (Extent == dynamic_extent)
   527             assert(Count <= size());
   528             assert(Count <= (size() - Offset));
   532             static_assert(Count <= extent);
   533             static_assert(Count <= (extent - Offset));
   536         if (Extent == dynamic_extent) {
   538             assert((size() > Count or size() == Count ) and 
"Count exceeds span size");
   539             assert( (Count < (size() - Offset) or Count == (size() - Offset)) and 
"Subspan ends past the span's end");
   542             assert((Count <= extent) and 
"Count exceeds span extent");
   543             assert(Count <= (extent - Offset) and  
"Subspan ends past the span's extent");
   547         return {data() + Offset, Count};
   550     template<std::
size_t Offset>
   551     constexpr KAT_HD 
auto   552     subspan<Offset, dynamic_extent>() 
const noexcept
   553     -> 
span<element_type, S_subspan_extent<Offset, dynamic_extent>()>
   555     #if __cplusplus >= 201703L   556         if constexpr KAT_HD (Extent == dynamic_extent)
   557             assert(Offset <= size());
   559             static_assert(Offset <= extent);
   561         if (Extent == dynamic_extent) {
   562             assert(Offset <= size() and 
"Subspan offset exceeds span size");
   565             assert((Offset <= Extent) and  
"Subspan offset exceeds fixed span extent");
   568         return {data() + Offset, size() - Offset};
   572     subspan(size_type offset, size_type count = dynamic_extent) 
const   575         assert(offset <= size());
   576         if (count == dynamic_extent) {
   577             count = size() - offset;
   581             assert(count <= size());
   582             assert(offset + count <= size());
   584         return {data() + offset, count};
   588 #if __cplusplus >= 202001L   589     [[no_unique_address]]
   595 #if __cplusplus < 201703L   596 template<
typename Type, std::
size_t Extent>
   601 #if __cplusplus >= 201703L   603   template<
typename Type, std::
size_t ArrayExtent>
   606   template<
typename Type, std::
size_t ArrayExtent>
   609   template<
typename Type, std::
size_t ArrayExtent>
   612   template<
typename Type, std::
size_t ArrayExtent>
   616   template<
typename Type, std::
size_t ArrayExtent>
   617     span(
const std::array<Type, ArrayExtent>&)
   620   template<contiguous_iterator Iter, 
typename Sentinel>
   624   template<
typename Range>
   629 #if __cplusplus >= 201703L   630 template<
typename Type, std::
size_t Extent>
   634     return {
reinterpret_cast<const byte*
>(sp.data()), sp.size_bytes()};
   637 template<
typename Type, std::
size_t Extent>
   641     return {
reinterpret_cast<byte*
>(sp.data()), sp.size_bytes()};
   659 span<Type> make_span(Type* ptr, std::size_t count)
   664 template<
class Type, std::
size_t Extent>
   671 template<
class Type, std::
size_t Extent>
   679 template<
class Type, std::
size_t Extent>
   687 template<
class Container>
   690 make_span(Container &container)
   695 template<
class Container>
   698 make_span(
const Container &container)
   703 template<
class Po
inter>
   706 make_span(Pointer& container, std::size_t count)
   711 template<
class Po
inter>
   714 make_span(Pointer& container)
   724 template<std::
size_t Index, 
typename Type, std::
size_t Extent>
   725 constexpr KAT_HD Type&
   728     static_assert(Extent != kat::dynamic_extent and Index < Extent,
   729         "get<I> can only be used with a span of non-dynamic (fixed) extent");
   736 template<
typename Type, std::
size_t Extent>
   737 struct tuple_size<
kat::span<Type, Extent>> : 
public std::integral_constant<std::size_t, Extent> {
   738     static_assert(Extent != kat::dynamic_extent, 
"tuple_size can only "   739         "be used with a span of non-dynamic (fixed) extent");
   742 template<std::
size_t Index, 
typename Type, std::
size_t Extent>
   744     static_assert(Extent != kat::dynamic_extent, 
"tuple_element can only "   745         "be used with a span of non-dynamic (fixed) extent");
   746     static_assert(Index < Extent, 
"Index is less than Extent");
   750 #if __cplusplus >= 202001L   753     template<
typename> 
extern inline const bool enable_safe_range;
   755     template<
typename _ElementType, std::
size_t Extent>
   756     inline constexpr KAT_HD 
bool   757     enable_safe_range<kat::span<_ElementType, Extent>> = 
true;
   763 #endif // KAT_CONTAINERS_SPAN_HPP_ 
Definition: array.hpp:353
 
Definition: common.hpp:16
 
This file implements kat::array, an equivalent of C++11's std::array which may be used both in host-s...
 
Definition: array.hpp:358
 
A standard container for storing a fixed size sequence of elements, based on std::array - but fully G...
Definition: array.hpp:81