30 #ifndef BPSTD_SPAN_HPP
31 #define BPSTD_SPAN_HPP
33 #include "detail/config.hpp"
34 #include "detail/proxy_iterator.hpp"
44 BPSTD_COMPILER_DIAGNOSTIC_PREAMBLE
52 BPSTD_CPP17_INLINE constexpr
auto dynamic_extent =
static_cast<std::size_t
>(-1);
56 template <std::
size_t Extent>
60 constexpr extent_storage() noexcept = default;
62 template <std::
size_t UExtent>
63 constexpr explicit extent_storage(extent_storage<UExtent>)
67 "Extent must be the same size as UExtent"
71 constexpr
explicit extent_storage(std::size_t)
76 constexpr std::size_t
size() const noexcept
83 class extent_storage<dynamic_extent>
86 template <std::
size_t Extent>
87 constexpr
explicit extent_storage(extent_storage<Extent> ext)
93 constexpr
explicit extent_storage(std::size_t size)
99 constexpr std::size_t
size() const noexcept
109 template <
typename T, std::
size_t Extent>
110 class span_storage_type :
public extent_storage<Extent>
117 template <
typename ExtentType>
118 constexpr span_storage_type(T* data, ExtentType ext)
119 : extent_storage<Extent>(ext),
130 using extent_storage<Extent>::size;
132 constexpr T*
data() const noexcept {
return m_data; }
142 template <std::
size_t From, std::
size_t To>
143 struct is_allowed_extent_conversion
144 : bool_constant<(From == To) || (To == dynamic_extent)>{};
146 template <std::
size_t Extent, std::
size_t Offset, std::
size_t Count>
147 struct compute_subspan_size
148 : integral_constant<std::size_t,
149 (Count != dynamic_extent)
151 : ((Extent != dynamic_extent) ? (Extent - Offset) : Extent)
154 template <
typename It>
155 using iter_reference =
typename std::iterator_traits<It>::reference;
157 template <
typename It,
typename T>
158 using is_iter_convertible = conjunction<
159 is_same<remove_cvref_t<iter_reference<It>>,remove_cv_t<T>>,
160 is_convertible<iter_reference<It>,remove_cv_t<T>>
181 template <
typename T, std::
size_t Extent = dynamic_extent>
189 using element_type = T;
190 using value_type = remove_cv_t<T>;
191 using size_type = std::size_t;
192 using difference_type = std::ptrdiff_t;
194 using pointer = element_type*;
195 using const_pointer =
const element_type*;
196 using reference = element_type&;
197 using const_reference =
const element_type&;
199 using iterator = detail::proxy_iterator<T*,detail::span_storage_type<T,Extent>>;
200 using reverse_iterator = std::reverse_iterator<iterator>;
207 BPSTD_CPP17_INLINE
static constexpr std::size_t extent = Extent;
218 template <std::size_t UExtent = Extent,
219 typename = enable_if_t<detail::is_allowed_extent_conversion<0,UExtent>::value>>
220 constexpr
span() noexcept;
234 template <
typename It,
235 enable_if_t<(Extent == bpstd::dynamic_extent) &&
237 constexpr
span(It it, size_type count) noexcept;
238 template <
typename It,
239 enable_if_t<(Extent != bpstd::dynamic_extent) &&
241 constexpr
explicit span(It it, size_type count) noexcept;
253 template <
typename It,
typename End,
254 enable_if_t<(Extent == bpstd::dynamic_extent) &&
256 constexpr
span(It it, End end) noexcept;
257 template <
typename It,
typename End,
258 enable_if_t<(Extent != bpstd::dynamic_extent) &&
260 constexpr
explicit span(It it, End end) noexcept;
270 template <std::size_t N,
271 typename = enable_if_t<detail::is_allowed_extent_conversion<N,Extent>::value>>
273 constexpr
span(element_type (&arr)[N]) noexcept;
284 template <
typename U, std::size_t N,
285 typename = enable_if_t<detail::is_allowed_extent_conversion<N,Extent>::value>>
287 constexpr
span(std::array<U, N>& arr) noexcept;
288 template <
typename U, std::size_t N,
289 typename = enable_if_t<detail::is_allowed_extent_conversion<N,Extent>::value>>
291 constexpr
span(
const std::array<U, N>& arr) noexcept;
304 template <
typename U, std::size_t N,
305 typename = enable_if_t<detail::is_allowed_extent_conversion<N,Extent>::value>>
312 constexpr
span(
const span& other) noexcept =
default;
331 constexpr reference
front()
const noexcept;
337 constexpr reference
back()
const noexcept;
344 constexpr reference
operator[](size_type idx)
const noexcept;
349 constexpr pointer
data()
const noexcept;
359 constexpr size_type
size()
const noexcept;
364 constexpr size_type
size_bytes()
const noexcept;
369 constexpr
bool empty()
const noexcept;
382 template <std::
size_t Count>
401 template <std::
size_t Count>
420 template <std::
size_t Offset, std::
size_t Count = dynamic_extent>
431 std::size_t count = dynamic_extent)
const;
438 constexpr iterator begin()
const noexcept;
439 constexpr iterator end()
const noexcept;
440 constexpr reverse_iterator rbegin()
const noexcept;
441 constexpr reverse_iterator rend()
const noexcept;
448 using storage_type = detail::span_storage_type<element_type,Extent>;
450 storage_type m_storage;
465 template <
typename T, std::
size_t N>
472 template <
typename T, std::
size_t N>
477 template <
typename T, std::
size_t Extent>
488 template <
typename T, std::
size_t Extent>
489 template <std::
size_t UExtent,
typename>
490 inline BPSTD_INLINE_VISIBILITY constexpr
493 : m_storage{
nullptr, detail::extent_storage<0>{}}
498 template <
typename T, std::
size_t Extent>
499 template <
typename It,
500 bpstd::enable_if_t<(Extent == bpstd::dynamic_extent) &&
502 inline BPSTD_INLINE_VISIBILITY constexpr
510 template <
typename T, std::
size_t Extent>
511 template <
typename It,
512 bpstd::enable_if_t<(Extent != bpstd::dynamic_extent) &&
514 inline BPSTD_INLINE_VISIBILITY constexpr
522 template <
typename T, std::
size_t Extent>
523 template <
typename It,
typename End,
524 bpstd::enable_if_t<(Extent == bpstd::dynamic_extent) &&
526 inline BPSTD_INLINE_VISIBILITY constexpr
529 : m_storage{
to_address(it),
static_cast<size_type
>(end - it)}
534 template <
typename T, std::
size_t Extent>
535 template <
typename It,
typename End,
536 bpstd::enable_if_t<(Extent != bpstd::dynamic_extent) &&
538 inline BPSTD_INLINE_VISIBILITY constexpr
541 : m_storage{
to_address(it),
static_cast<size_type
>(end - it)}
546 template <
typename T, std::
size_t Extent>
547 template <std::
size_t N,
typename>
548 inline BPSTD_INLINE_VISIBILITY constexpr
551 : m_storage{
static_cast<element_type*
>(arr), detail::extent_storage<N>{}}
556 template <
typename T, std::
size_t Extent>
557 template <
typename U, std::
size_t N,
typename>
558 inline BPSTD_INLINE_VISIBILITY constexpr
561 : m_storage{arr.data(), detail::extent_storage<N>{}}
566 template <
typename T, std::
size_t Extent>
567 template <
typename U, std::
size_t N,
typename>
568 inline BPSTD_INLINE_VISIBILITY constexpr
571 : m_storage{arr.data(), detail::extent_storage<N>{}}
576 template <
typename T, std::
size_t Extent>
577 template <
typename U, std::
size_t N,
typename>
578 inline BPSTD_INLINE_VISIBILITY constexpr
581 : m_storage{s.
data(), detail::extent_storage<N>{s.
size()}}
590 template <
typename T, std::
size_t Extent>
591 inline BPSTD_INLINE_VISIBILITY constexpr
592 typename bpstd::span<T,Extent>::reference
599 template <
typename T, std::
size_t Extent>
600 inline BPSTD_INLINE_VISIBILITY constexpr
601 typename bpstd::span<T,Extent>::reference
605 return data()[m_storage.size()-1];
608 template <
typename T, std::
size_t Extent>
609 inline BPSTD_INLINE_VISIBILITY constexpr
610 typename bpstd::span<T,Extent>::reference
617 template <
typename T, std::
size_t Extent>
618 inline BPSTD_INLINE_VISIBILITY constexpr
619 typename bpstd::span<T,Extent>::pointer
623 return m_storage.data();
630 template <
typename T, std::
size_t Extent>
631 inline BPSTD_INLINE_VISIBILITY constexpr
632 typename bpstd::span<T,Extent>::size_type
636 return m_storage.size();
639 template <
typename T, std::
size_t Extent>
640 inline BPSTD_INLINE_VISIBILITY constexpr
641 typename bpstd::span<T,Extent>::size_type
645 return size() *
sizeof(T);
648 template <
typename T, std::
size_t Extent>
649 inline BPSTD_INLINE_VISIBILITY constexpr
660 template <
typename T, std::
size_t Extent>
661 template <std::
size_t Count>
662 inline BPSTD_INLINE_VISIBILITY constexpr
669 "A Count larger than Extent is ill-formed"
675 template <
typename T, std::
size_t Extent>
676 inline BPSTD_INLINE_VISIBILITY constexpr
681 return {
data(), count};
686 template <
typename T, std::
size_t Extent>
687 template <std::
size_t Count>
688 inline BPSTD_INLINE_VISIBILITY constexpr
695 "A Count larger than Extent is ill-formed"
701 template <
typename T, std::
size_t Extent>
702 inline BPSTD_INLINE_VISIBILITY constexpr
707 return {
data() + (
size() - count), count};
712 template <
typename T, std::
size_t Extent>
713 template <std::
size_t Offset, std::
size_t Count>
714 inline BPSTD_INLINE_VISIBILITY constexpr
719 using result_type =
span<
721 detail::compute_subspan_size<Extent,Offset,Count>::value
726 (Count == dynamic_extent) ? (
size() - Offset) : Count
730 template <
typename T, std::
size_t Extent>
731 inline BPSTD_INLINE_VISIBILITY constexpr
738 (count == dynamic_extent) ? (
size() - offset) : count
746 template <
typename T, std::
size_t Extent>
747 inline BPSTD_INLINE_VISIBILITY constexpr
748 typename bpstd::span<T,Extent>::iterator
752 return iterator{
data()};
755 template <
typename T, std::
size_t Extent>
756 inline BPSTD_INLINE_VISIBILITY constexpr
757 typename bpstd::span<T,Extent>::iterator
764 template <
typename T, std::
size_t Extent>
765 inline BPSTD_INLINE_VISIBILITY constexpr
766 typename bpstd::span<T,Extent>::reverse_iterator
770 return reverse_iterator(end());
773 template <
typename T, std::
size_t Extent>
774 inline BPSTD_INLINE_VISIBILITY constexpr
775 typename bpstd::span<T,Extent>::reverse_iterator
779 return reverse_iterator(begin());
790 template <
typename T, std::
size_t N>
791 inline bpstd::span<
const bpstd::byte,
sizeof(T) * N> bpstd::as_bytes(span<T, N> s)
794 return {
reinterpret_cast<const byte*
>(s.data()), s.size_bytes()};
797 template <
typename T, std::
size_t N>
798 inline bpstd::span<bpstd::byte,
sizeof(T) * N> bpstd::as_writable_bytes(span<T, N> s)
801 return {
reinterpret_cast<byte*
>(s.data()), s.size_bytes()};
804 BPSTD_COMPILER_DIAGNOSTIC_POSTAMBLE