20 using element_type = T;
21 using value_type = std::remove_const_t<element_type>;
22 using size_type = std::size_t;
23 using difference_type = std::ptrdiff_t;
24 using reference = element_type&;
25 using const_reference =
const value_type&;
26 using pointer = element_type*;
27 using const_pointer =
const value_type*;
30 template<
bool IsConst>
34 using view_type = std::conditional_t<IsConst, const ArrayView, ArrayView>;
36 view_type* view_ =
nullptr;
40 using iterator_concept = std::random_access_iterator_tag;
41 using iterator_category = std::random_access_iterator_tag;
42 using value_type = ArrayView::value_type;
43 using difference_type = std::ptrdiff_t;
44 using reference = std::conditional_t<IsConst, const_reference, ArrayView::reference>;
48 : view_(view), index_(index)
51 template<
bool OtherConst>
52 requires (IsConst && !OtherConst)
54 : view_(other.view_), index_(other.index_)
57 reference operator*()
const {
return (*view_)[index_];}
58 reference operator[](difference_type offset)
const {
return *(*
this + offset);}
61 basic_iterator operator++(
int) {
auto copy = *
this; ++*
this;
return copy;}
63 basic_iterator operator--(
int) {
auto copy = *
this; --*
this;
return copy;}
67 index_ =
static_cast<size_type
>(
static_cast<difference_type
>(index_) + offset);
71 basic_iterator& operator-=(difference_type offset) {
return *
this += -offset;}
92 return static_cast<difference_type
>(lhs.index_) -
93 static_cast<difference_type
>(rhs.index_);
99 return lhs.index_ <=> rhs.index_;
117 std::is_const_v<element_type> &&
118 !std::is_const_v<U> &&
119 std::same_as<value_type, std::remove_const_t<U>>
122 : data_(other.data()),
123 shape_(other.shape()),
124 strides_(other.strides())
128 const Shape& shape() const noexcept
134 const Shape& strides() const noexcept
140 size_type ndim() const noexcept
146 size_type rank() const noexcept
148 return shape_.
rank();
152 size_type size() const noexcept
158 bool empty() const noexcept
164 pointer data() noexcept
170 const_pointer data() const noexcept
176 const_view as_const()
const
178 return const_view(data_, shape_, strides_);
181 reference operator[](size_type index)
183 return data_[flat_offset(index)];
186 const_reference operator[](size_type index)
const
188 return data_[flat_offset(index)];
191 iterator begin() noexcept {
return iterator(
this, 0);}
192 const_iterator begin() const noexcept {
return const_iterator(
this, 0);}
193 const_iterator cbegin() const noexcept {
return const_iterator(
this, 0);}
194 iterator end() noexcept {
return iterator(
this, size());}
195 const_iterator end() const noexcept {
return const_iterator(
this, size());}
196 const_iterator cend() const noexcept {
return const_iterator(
this, size());}
198 template<
typename... Rest>
199requires ((std::is_integral_v<Rest>) && ...)
200reference operator()(size_type first, Rest... rest)
202 constexpr size_type count =
sizeof...(Rest) + 1;
207 "The number of indices must match the view rank.");
210 const std::array<size_type, count> indices{
212 static_cast<size_type
>(rest)...
215 return data_[indexing::offset(strides_, indices)];
218template<
typename... Rest>
219requires ((std::is_integral_v<Rest>) && ...)
220const_reference operator()(size_type first, Rest... rest)
const
222 constexpr size_type count =
sizeof...(Rest) + 1;
227 "The number of indices must match the view rank.");
230 const std::array<size_type, count> indices{
232 static_cast<size_type
>(rest)...
235 return data_[indexing::offset(strides_, indices)];
238reference at(difference_type index)
240 index = indexing::normalize_index(index, size());
241 return (*
this)[
static_cast<size_type
>(index)];
244const_reference at(difference_type index)
const
246 index = indexing::normalize_index(index, size());
247 return (*
this)[
static_cast<size_type
>(index)];
250reference at(
const std::vector<difference_type>& indices)
252 return data_[checked_offset(indices)];
255const_reference at(
const std::vector<difference_type>& indices)
const
257 return data_[checked_offset(indices)];
262 size_type flat_offset(size_type index)
const
264 size_type offset = 0;
266 for (size_type dim = rank(); dim-- > 0;)
268 const size_type coordinate = index % shape_[dim];
269 index /= shape_[dim];
270 offset += coordinate * strides_[dim];
276 size_type checked_offset(
277 const std::vector<difference_type>& indices)
const
279 if (indices.size() != rank())
282 "The number of indices must match the view rank.");
285 size_type offset = 0;
287 for (size_type dim = 0; dim < rank(); ++dim)
289 const difference_type index =
290 indexing::normalize_index(
295 static_cast<size_type
>(index) *