11 #include <type_traits> 14 #include <core/util/Verify.hpp> 18 constexpr std::size_t DynamicExtent = std::numeric_limits<std::size_t>::max();
20 namespace span_helpers {
26 template <
size_t Extent>
27 struct IsDynamicExtent {
28 static constexpr
bool value =
false;
32 struct IsDynamicExtent<DynamicExtent> {
33 static constexpr
bool value =
true;
36 template <
size_t Index,
size_t Extent>
38 static constexpr
bool value = (Index < Extent);
41 template <
size_t Index>
42 struct IsIndexValid<Index, DynamicExtent> {
43 static constexpr
bool value =
false;
50 template <
size_t Extent>
51 class SpanSize final {
54 ~SpanSize() =
default;
56 constexpr
size_t Size() const noexcept {
return size_; }
59 static constexpr
size_t size_ = Extent;
63 class SpanSize<DynamicExtent> final {
66 ~SpanSize() =
default;
73 size_t Size() const noexcept {
return size_; }
92 template <
typename T,
size_t Extent = DynamicExtent>
96 using pointer =
typename std::add_pointer<value_type>::type;
97 using reference =
typename std::add_lvalue_reference<value_type>::type;
98 using iterator = pointer;
100 using const_value_type =
typename std::add_const<value_type>::type;
101 using const_pointer =
typename std::add_pointer<const_value_type>::type;
102 using const_iterator = const_pointer;
104 template <
size_t Extent_>
105 using SpanSize = span_helpers::SpanSize<Extent_>;
107 template <
size_t Extent_>
108 using IsDynamicExtent = span_helpers::IsDynamicExtent<Extent_>;
110 template <
size_t Index,
size_t Extent_>
111 using IsIndexValid = span_helpers::IsIndexValid<Index, Extent_>;
113 class SliceIterator final {
115 SliceIterator(pointer p,
size_t stride)
121 bool operator==(
const SliceIterator& other)
const noexcept
123 return ptr_ == other.ptr_ && stride_ == other.stride_;
126 bool operator!=(
const SliceIterator& other)
const noexcept {
return !(*
this == other); }
128 SliceIterator& operator++() noexcept
134 SliceIterator operator++(
int)
const noexcept {
return SliceIterator(ptr_ + stride_, stride_); }
136 Span<T> operator*()
const {
return Span<T>(ptr_, stride_); }
143 template <
size_t Str
ide>
144 class StaticSliceIterator final {
146 StaticSliceIterator(pointer p)
151 bool operator==(
const StaticSliceIterator<Stride>& other)
const noexcept
153 return ptr_ == other.ptr_;
156 bool operator!=(
const StaticSliceIterator<Stride>& other)
const noexcept
158 return !(*
this == other);
161 StaticSliceIterator& operator++() noexcept
167 StaticSliceIterator operator++(
int)
const noexcept
169 return StaticSliceIterator<Stride>(ptr_ + Stride);
172 Span<T, Stride> operator*()
const {
return Span<T, Stride>(ptr_); }
178 template <
typename Iterator>
179 class IteratorProvider final {
181 IteratorProvider(Iterator begin, Iterator end)
187 Iterator begin()
const {
return begin_; }
189 Iterator end()
const {
return end_; }
198 Span(
const Span<T, Extent>&) =
default;
199 Span(Span<T, Extent>&&) =
default;
201 Span<T, Extent>& operator=(
const Span<T, Extent>&) =
default;
202 Span<T, Extent>& operator=(Span<T, Extent>&&) =
default;
204 template <
size_t Extent__ = Extent,
205 typename std::enable_if<IsDynamicExtent<Extent__>::value,
int>::type = 0>
212 template <
size_t Extent__ = Extent,
213 typename std::enable_if<!IsDynamicExtent<Extent__>::value,
int>::type = 0>
219 template <
size_t Extent__ = Extent,
220 typename std::enable_if<IsDynamicExtent<Extent__>::value,
int>::type = 0>
221 Span(pointer p,
size_t size)
222 : ptr_(size == 0 ? nullptr : p)
231 pointer Data() const noexcept {
return ptr_; }
233 size_t Size() const noexcept {
return size_.Size(); }
235 constexpr
bool IsEmpty() const noexcept {
return Size() == 0; }
241 reference operator[](
size_t index)
const 243 VerifyDebugIsTrue(index < Size(), TuriErrorCode::IndexOutOfBounds);
247 reference At(
size_t index)
const 249 VerifyIsTrue(index < Size(), TuriErrorCode::IndexOutOfBounds);
256 template <size_t Index, typename std::enable_if<!IsDynamicExtent<Extent>::value &&
257 IsIndexValid<Index, Extent>::value,
259 reference Get()
const 261 return (*
this)[Index];
268 Span<T> Slice(
size_t index)
const 270 VerifyIsTrue(index < Size(), TuriErrorCode::IndexOutOfBounds);
271 return Span<T>(Data() + index, Size() - index);
274 Span<T> Slice(
size_t index,
size_t size)
const 276 VerifyIsTrue(size > 0 && index < Size() && index + size <= Size(),
277 TuriErrorCode::IndexOutOfBounds);
278 return Span<T>(Data() + index, size);
281 Span<T> SliceByDimension(
size_t num_slices,
size_t slice_index)
const 283 VerifyIsTrue(Size() % num_slices == 0, TuriErrorCode::IndexOutOfBounds);
284 size_t stride = Size() / num_slices;
285 return Slice(slice_index * stride, stride);
292 template <
size_t NewExtent>
293 Span<T, NewExtent> StaticResize()
const 295 VerifyIsTrue(NewExtent <= Size(), TuriErrorCode::IndexOutOfBounds);
296 return Span<T, NewExtent>(Data());
303 iterator begin() const noexcept {
return Data(); }
305 iterator end() const noexcept {
return Data() + Size(); }
307 const_iterator cbegin() const noexcept {
return Data(); }
309 const_iterator cend() const noexcept {
return Data() + Size(); }
315 IteratorProvider<SliceIterator> IterateSlices(
size_t sliceSize)
const 317 VerifyIsTrue(Size() % sliceSize == 0, TuriErrorCode::IndexOutOfBounds);
319 return IteratorProvider<SliceIterator>(SliceIterator(Data(), sliceSize),
320 SliceIterator(Data() + Size(), sliceSize));
323 template <
size_t SliceSize>
324 IteratorProvider<StaticSliceIterator<SliceSize>> IterateSlices()
const 326 VerifyIsTrue(Size() % SliceSize == 0, TuriErrorCode::IndexOutOfBounds);
328 return IteratorProvider<StaticSliceIterator<SliceSize>>(
329 StaticSliceIterator<SliceSize>(Data()), StaticSliceIterator<SliceSize>(Data() + Size()));
332 IteratorProvider<SliceIterator> IterateByDimension(
size_t dim)
const 334 return IterateSlices(Size() / dim);
339 SpanSize<Extent> size_;
354 template <
typename T>
355 Span<T> MakeSpan(std::vector<T>& v) noexcept
357 return Span<T>(v.data(), v.size());
360 template <typename T, typename MutableT = typename std::remove_const<T>::type>
361 Span<T> MakeSpan(
const std::vector<MutableT>& v) noexcept
363 return Span<T>(v.data(), v.size());
366 template <typename T, typename ConstT = typename std::add_const<T>::type>
367 Span<ConstT> MakeSpan(
const std::vector<T>& v) noexcept
369 return Span<ConstT>(v.data(), v.size());
384 template <
typename T,
size_t N>
385 Span<T, N> MakeSpan(std::array<T, N>& v) noexcept
387 return Span<T, N>(v.data());
390 template <typename T, size_t N, typename MutableT = typename std::remove_const<T>::type>
391 Span<T, N> MakeSpan(
const std::array<MutableT, N>& v) noexcept
393 return Span<T, N>(v.data());
396 template <typename T, size_t N, typename ConstT = typename std::add_const<T>::type>
397 Span<ConstT, N> MakeSpan(
const std::array<T, N>& v) noexcept
399 return Span<ConstT, N>(v.data());