307class span : span_detail::span_base<Extent> {
310 using base = span_detail::span_base<Extent>;
314 T* data_ptr_{
nullptr};
317 static constexpr std::size_t max_extent{
318 static_cast<std::size_t>(
static_cast<std::size_t>(std::numeric_limits<std::ptrdiff_t>::max()) /
sizeof(T))
323 static_assert((Extent == dynamic_extent) || Extent <= max_extent,
"span extent exceeds its max value");
328 template <std::size_t TargetExtent>
329 static constexpr bool is_valid_source_extent_v{span_detail::is_valid_source_extent(Extent, TargetExtent)};
335 static constexpr auto is_valid_runtime_size(std::size_t target_extent)
noexcept ->
bool {
336 return span_detail::is_valid_runtime_size(Extent, target_extent, max_extent);
340 class pre_checked_size {
343 constexpr explicit pre_checked_size()
noexcept =
default;
356 constexpr span(pre_checked_size, T* data_pointer, std::size_t data_size)
noexcept
357 : base(span_detail::span_construction_tag{}, data_size),
358 data_ptr_(data_pointer) {}
366 using element_type = T;
368 using value_type = arene::base::remove_cvref_t<T>;
370 using size_type = std::size_t;
374 using const_pointer = T
const*;
376 using reference = T&;
378 using const_reference = T
const&;
380 using iterator = detail::wrapped_iterator<pointer, span_detail::span_iter_passkey>;
382 using const_iterator = detail::wrapped_iterator<const_pointer, span_detail::span_iter_passkey>;
384 using reverse_iterator = ::arene::base::reverse_iterator<iterator>;
386 using const_reverse_iterator = ::arene::base::reverse_iterator<const_iterator>;
388 using difference_type =
typename iterator::difference_type;
392 static constexpr std::integral_constant<std::size_t, Extent> extent{};
398 ARENE_NODISCARD
constexpr auto ssize()
const noexcept -> difference_type {
399 return static_cast<difference_type>(
this->size());
404 constexpr span()
noexcept =
default;
409 constexpr span(span
const& other) =
default;
412 constexpr span(span&& other) =
default;
417 constexpr auto operator=(span
const& other) -> span& =
default;
420 constexpr auto operator=(span&& other) -> span& =
default;
437 template <
typename U, constraints<std::enable_if_t<arene::base::is_array_convertible_v<U, T>>> =
nullptr>
439 constexpr span(U* data_pointer, std::size_t data_size)
noexcept
440 : span(pre_checked_size{}, data_pointer, data_size) {
441 ARENE_PRECONDITION(is_valid_runtime_size(data_size));
454 template <std::size_t N, constraints<std::enable_if_t<is_valid_source_extent_v<N>>> =
nullptr>
456 constexpr span(T (&array)[N])
noexcept
458 : span(pre_checked_size{}, array, N) {}
473 template <
typename U, std::size_t N>
478 std::enable_if_t<span_detail::has_member_data_v<ArrayLikeT<U, N>>>,
479 std::enable_if_t<span_detail::has_tuple_size_v<ArrayLikeT<U, N>>>,
480 std::enable_if_t<std::tuple_size<ArrayLikeT<U, N>>::value == N>,
481 std::enable_if_t<arene::base::is_array_convertible_v<U, T>>,
482 std::enable_if_t<is_valid_source_extent_v<N>>> =
nullptr>
484 constexpr span(ArrayLikeT<U, N>& array)
noexcept
485 : span(pre_checked_size{}, array.data(), N) {}
500 template <
typename U, std::size_t N>
505 std::enable_if_t<span_detail::has_member_data_v<ArrayLikeT<U, N>>>,
506 std::enable_if_t<span_detail::has_tuple_size_v<ArrayLikeT<U, N>>>,
507 std::enable_if_t<std::tuple_size<ArrayLikeT<U, N>>::value == N>,
508 std::enable_if_t<std::is_const<T>::value && arene::base::is_array_convertible_v<U, T>>,
509 std::enable_if_t<is_valid_source_extent_v<N>>> =
nullptr>
511 constexpr span(ArrayLikeT<U, N>
const& array)
noexcept
512 : span(pre_checked_size{}, array.data(), N) {}
530 template <
typename U, std::size_t N>
535 std::enable_if_t<span_detail::has_member_data_v<ArrayLikeT<U, N>>>,
536 std::enable_if_t<span_detail::has_tuple_size_v<ArrayLikeT<U, N>>>,
537 std::enable_if_t<std::tuple_size<ArrayLikeT<U, N>>::value == N>,
538 std::enable_if_t<arene::base::is_array_convertible_v<U, T>>,
539 std::enable_if_t<is_valid_source_extent_v<N>>> =
nullptr>
541 constexpr span(ArrayLikeT<U, N>&& array)
noexcept
542 : span(pre_checked_size{}, array.data(), N) {}
560 template <
typename U, std::size_t N>
565 std::enable_if_t<span_detail::has_member_data_v<ArrayLikeT<U, N>>>,
566 std::enable_if_t<span_detail::has_tuple_size_v<ArrayLikeT<U, N>>>,
567 std::enable_if_t<std::tuple_size<ArrayLikeT<U, N>>::value == N>,
568 std::enable_if_t<std::is_const<T>::value && arene::base::is_array_convertible_v<U, T>>,
569 std::enable_if_t<is_valid_source_extent_v<N>>> =
nullptr>
571 constexpr span(ArrayLikeT<U, N>
const&& array)
noexcept
572 : span(pre_checked_size{}, array.data(), N) {}
579 std::size_t OtherExtent,
580 constraints<std::enable_if_t<
581 !span_detail::is_dynamic_extent(Extent) && !span_detail::is_dynamic_extent(OtherExtent) &&
582 Extent != OtherExtent>> =
nullptr>
583 constexpr span(span<U, OtherExtent>&& other)
noexcept =
delete;
601 !span_detail::has_tuple_size_v<arene::base::remove_cvref_t<Container>> &&
602 span_detail::is_dynamic_extent(Extent)>,
603 std::enable_if_t<arene::base::is_array_convertible_v<
604 arene::base::remove_reference_t<
decltype(*std::declval<Container>().data())>,
607 constexpr span(Container&& source)
noexcept
608 : span(source.data(), source.size()) {}
630 !span_detail::has_tuple_size_v<arene::base::remove_cvref_t<Container>> &&
631 !span_detail::is_dynamic_extent(Extent)>,
632 std::enable_if_t<arene::base::is_array_convertible_v<
633 arene::base::remove_reference_t<
decltype(*std::declval<Container>().data())>,
636 explicit constexpr span(Container&& source)
noexcept
637 : span(source.data(), source.size()) {
638 ARENE_PRECONDITION(source.size() == Extent);
653 std::size_t OtherExtent,
655 std::enable_if_t<arene::base::is_array_convertible_v<U, T>>,
656 std::enable_if_t<is_valid_source_extent_v<OtherExtent>>> =
nullptr>
658 constexpr span(span<U, OtherExtent>
const& other)
noexcept
660 : span(other.data(), (!span_detail::is_dynamic_extent(Extent)) ? Extent : other.size()) {}
670 std::size_t OtherExtent,
672 std::enable_if_t<arene::base::is_array_convertible_v<U, T>>,
673 std::enable_if_t<(!span_detail::is_dynamic_extent(Extent)) && span_detail::is_dynamic_extent(OtherExtent)>> =
675 explicit constexpr span(span<U, OtherExtent>
const& other)
noexcept
676 : span(other.data(), Extent) {}
683 ARENE_NODISCARD
constexpr auto empty()
const noexcept ->
bool {
return this->size() == 0U; }
688 ARENE_NODISCARD
constexpr auto size_bytes()
const noexcept -> std::size_t {
return this->size() *
sizeof(T); }
693 ARENE_NODISCARD
constexpr auto data()
const noexcept -> T* {
return data_ptr_; }
701 constexpr auto operator[](std::size_t index)
const noexcept -> T& {
702 ARENE_PRECONDITION(index <
this->size());
703 return begin()[
static_cast<difference_type>(index)];
710 ARENE_NODISCARD
constexpr auto front()
const noexcept -> T& {
711 ARENE_PRECONDITION(!empty());
719 ARENE_NODISCARD
constexpr auto back()
const noexcept -> T& {
720 ARENE_PRECONDITION(!empty());
721 return this->operator[](
this->size() - 1U);
732 std::size_t UE = Extent,
733 constraints<std::enable_if_t<span_detail::is_dynamic_extent(UE)>> =
nullptr>
734 ARENE_NODISCARD
constexpr auto first()
const noexcept -> span<T, Count> {
735 ARENE_PRECONDITION(Count <=
this->size());
736 return {data_ptr_, Count};
744 std::size_t UE = Extent,
745 constraints<std::enable_if_t<!span_detail::is_dynamic_extent(UE)>, std::enable_if_t<Count <= Extent>> =
nullptr>
746 ARENE_NODISCARD
constexpr auto first()
const noexcept -> span<T, Count> {
747 return {data_ptr_, Count};
757 ARENE_NODISCARD
constexpr auto first(std::size_t count)
const noexcept -> span<T> {
758 ARENE_PRECONDITION(count <=
this->size());
759 return {data_ptr_, count};
771 std::size_t UE = Extent,
772 constraints<std::enable_if_t<span_detail::is_dynamic_extent(UE)>> =
nullptr>
773 ARENE_NODISCARD
constexpr auto last()
const noexcept -> span<T, Count> {
774 ARENE_PRECONDITION(Count <=
this->size());
775 std::size_t
const offset{
this->size() - Count};
776 return span<T, Count>{arene::base::next(data_ptr_,
static_cast<std::ptrdiff_t>(offset)), Count};
784 std::size_t UE = Extent,
785 constraints<std::enable_if_t<!span_detail::is_dynamic_extent(UE)>, std::enable_if_t<Count <= Extent>> =
nullptr>
786 ARENE_NODISCARD
constexpr auto last()
const noexcept -> span<T, Count> {
787 std::size_t
const offset{
this->size() - Count};
788 return span<T, Count>{arene::base::next(data_ptr_,
static_cast<std::ptrdiff_t>(offset)), Count};
798 ARENE_NODISCARD
constexpr auto last(std::size_t count)
const noexcept -> span<T> {
799 ARENE_PRECONDITION(count <=
this->size());
800 std::size_t
const offset{
this->size() - count};
801 return span<T>{arene::base::next(data_ptr_,
static_cast<std::ptrdiff_t>(offset)), count};
814 std::size_t Count = span_detail::get_dynamic_extent(),
816 std::enable_if_t<Offset <= Extent>,
817 std::enable_if_t<span_detail::is_dynamic_extent(Count) && !span_detail::is_dynamic_extent(Extent)>> =
nullptr>
818 ARENE_NODISCARD
constexpr auto subspan()
const noexcept
819 -> span<T, span_detail::extent_for_subspan<Extent, Offset, Count>()> {
820 return last<Extent - Offset>();
830 std::size_t Count = span_detail::get_dynamic_extent(),
832 std::enable_if_t<Offset <= Extent>,
833 std::enable_if_t<!span_detail::is_dynamic_extent(Count) && !span_detail::is_dynamic_extent(Extent)>> =
835 ARENE_NODISCARD
constexpr auto subspan()
const noexcept
836 -> span<T, span_detail::extent_for_subspan<Extent, Offset, Count>()> {
837 return last<Extent - Offset>().
template first<Count>();
847 std::size_t Count = span_detail::get_dynamic_extent(),
849 std::enable_if_t<Offset <= Extent>,
850 std::enable_if_t<span_detail::is_dynamic_extent(Count) && span_detail::is_dynamic_extent(Extent)>> =
nullptr>
851 ARENE_NODISCARD
constexpr auto subspan()
const noexcept
852 -> span<T, span_detail::extent_for_subspan<Extent, Offset, Count>()> {
853 ARENE_PRECONDITION(Offset <=
this->size());
854 return last(
this->size() - Offset);
865 std::size_t Count = span_detail::get_dynamic_extent(),
867 std::enable_if_t<Offset <= Extent>,
868 std::enable_if_t<!span_detail::is_dynamic_extent(Count) && span_detail::is_dynamic_extent(Extent)>> =
nullptr>
869 ARENE_NODISCARD
constexpr auto subspan()
const noexcept
870 -> span<T, span_detail::extent_for_subspan<Extent, Offset, Count>()> {
871 ARENE_PRECONDITION(Offset <=
this->size());
872 return last(
this->size() - Offset).
template first<Count>();
885 ARENE_NODISCARD
constexpr auto subspan(std::size_t offset, std::size_t count = dynamic_extent)
const noexcept
887 ARENE_PRECONDITION(offset <=
this->size());
888 auto const last_start =
this->size() - offset;
889 if (span_detail ::is_dynamic_extent(count)) {
890 return last(last_start);
892 return last(last_start).first(count);
900 ARENE_NODISCARD
constexpr auto begin()
const noexcept -> iterator {
901 return iterator{span_detail::span_iter_passkey{}, data_ptr_};
907 ARENE_NODISCARD
constexpr auto cbegin()
const noexcept -> const_iterator {
908 return const_iterator{span_detail::span_iter_passkey{}, data_ptr_};
914 ARENE_NODISCARD
constexpr auto end()
const noexcept -> iterator {
915 return iterator{span_detail::span_iter_passkey{}, arene::base::next(data_ptr_, ssize())};
921 ARENE_NODISCARD
constexpr auto cend()
const noexcept -> const_iterator {
922 return const_iterator{span_detail::span_iter_passkey{}, arene::base::next(data_ptr_, ssize())};
928 ARENE_NODISCARD
constexpr auto rbegin()
const noexcept -> reverse_iterator {
return reverse_iterator(end()); }
933 ARENE_NODISCARD
constexpr auto crbegin()
const noexcept -> const_reverse_iterator {
934 return const_reverse_iterator(cend());
940 ARENE_NODISCARD
constexpr auto rend()
const noexcept -> reverse_iterator {
return reverse_iterator(begin()); }
945 ARENE_NODISCARD
constexpr auto crend()
const noexcept -> const_reverse_iterator {
946 return const_reverse_iterator(cbegin());