29 using difference_type = sarr_ext_soa_detail::size_type;
30 using size_type = sarr_ext_soa_detail::size_type;
41 sarr_ext_soa_iterator(uint8_t* ptr, uint32_t cnt, uint32_t idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
46 T operator->()
const {
49 iterator operator[](size_type offset)
const {
50 return iterator(m_ptr, m_cnt, m_idx + offset);
53 iterator& operator+=(size_type diff) {
57 iterator& operator-=(size_type diff) {
80 iterator operator+(size_type offset)
const {
81 return iterator(m_ptr, m_cnt, m_idx + offset);
83 iterator operator-(size_type offset)
const {
84 return iterator(m_ptr, m_cnt, m_idx + offset);
86 difference_type operator-(
const iterator& other)
const {
87 GAIA_ASSERT(m_ptr == other.m_ptr);
88 return (difference_type)(m_idx - other.m_idx);
91 GAIA_NODISCARD
bool operator==(
const iterator& other)
const {
92 GAIA_ASSERT(m_ptr == other.m_ptr);
93 return m_idx == other.m_idx;
95 GAIA_NODISCARD
bool operator!=(
const iterator& other)
const {
96 GAIA_ASSERT(m_ptr == other.m_ptr);
97 return m_idx != other.m_idx;
99 GAIA_NODISCARD
bool operator>(
const iterator& other)
const {
100 GAIA_ASSERT(m_ptr == other.m_ptr);
101 return m_idx > other.m_idx;
103 GAIA_NODISCARD
bool operator>=(
const iterator& other)
const {
104 GAIA_ASSERT(m_ptr == other.m_ptr);
105 return m_idx >= other.m_idx;
107 GAIA_NODISCARD
bool operator<(
const iterator& other)
const {
108 GAIA_ASSERT(m_ptr == other.m_ptr);
109 return m_idx < other.m_idx;
111 GAIA_NODISCARD
bool operator<=(
const iterator& other)
const {
112 GAIA_ASSERT(m_ptr == other.m_ptr);
113 return m_idx <= other.m_idx;
119 using value_type = T;
122 using difference_type = sarr_ext_soa_detail::size_type;
123 using size_type = sarr_ext_soa_detail::size_type;
129 const uint8_t* m_ptr;
136 T operator*()
const {
139 T operator->()
const {
142 iterator operator[](size_type offset)
const {
143 return iterator(m_ptr, m_cnt, m_idx + offset);
146 iterator& operator+=(size_type diff) {
150 iterator& operator-=(size_type diff) {
173 iterator operator+(size_type offset)
const {
174 return iterator(m_ptr, m_cnt, m_idx + offset);
176 iterator operator-(size_type offset)
const {
177 return iterator(m_ptr, m_cnt, m_idx + offset);
179 difference_type operator-(
const iterator& other)
const {
180 GAIA_ASSERT(m_ptr == other.m_ptr);
181 return (difference_type)(m_idx - other.m_idx);
184 GAIA_NODISCARD
bool operator==(
const iterator& other)
const {
185 GAIA_ASSERT(m_ptr == other.m_ptr);
186 return m_idx == other.m_idx;
188 GAIA_NODISCARD
bool operator!=(
const iterator& other)
const {
189 GAIA_ASSERT(m_ptr == other.m_ptr);
190 return m_idx != other.m_idx;
192 GAIA_NODISCARD
bool operator>(
const iterator& other)
const {
193 GAIA_ASSERT(m_ptr == other.m_ptr);
194 return m_idx > other.m_idx;
196 GAIA_NODISCARD
bool operator>=(
const iterator& other)
const {
197 GAIA_ASSERT(m_ptr == other.m_ptr);
198 return m_idx >= other.m_idx;
200 GAIA_NODISCARD
bool operator<(
const iterator& other)
const {
201 GAIA_ASSERT(m_ptr == other.m_ptr);
202 return m_idx < other.m_idx;
204 GAIA_NODISCARD
bool operator<=(
const iterator& other)
const {
205 GAIA_ASSERT(m_ptr == other.m_ptr);
206 return m_idx <= other.m_idx;
214 static_assert(mem::is_soa_layout_v<T>,
"sarr_ext_soa can be used only with soa types");
217 static_assert(N > 0);
219 using value_type = T;
220 using reference = T&;
221 using const_reference =
const T&;
223 using const_pointer =
const T*;
225 using difference_type = sarr_ext_soa_detail::difference_type;
226 using size_type = sarr_ext_soa_detail::size_type;
232 static constexpr size_type extent = N;
233 static constexpr uint32_t allocated_bytes = view_policy::get_min_byte_size(0, N);
237 size_type m_cnt = size_type(0);
245 constexpr sarr_ext_soa(size_type count, const_reference value)
noexcept {
255 template <
typename InputIt>
256 constexpr sarr_ext_soa(InputIt first, InputIt last)
noexcept {
257 const auto count = (size_type)core::distance(first, last);
260 if constexpr (std::is_pointer_v<InputIt>) {
261 for (size_type i = 0; i < count; ++i)
262 operator[](i) = first[i];
263 }
else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
264 for (size_type i = 0; i < count; ++i)
265 operator[](i) = *(first[i]);
268 for (
auto it = first; it != last; ++it)
269 operator[](++i) = *it;
278 GAIA_ASSERT(core::addressof(other) !=
this);
280 mem::move_elements<T, true>(m_data, other.m_data, other.size(), 0, extent, other.extent);
282 other.m_cnt = size_type(0);
291 GAIA_ASSERT(core::addressof(other) !=
this);
293 resize(other.size());
294 mem::copy_elements<T, true>(
295 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((
const uint8_t*)&other.m_data[0]), other.size(), 0, extent,
302 GAIA_ASSERT(core::addressof(other) !=
this);
305 mem::move_elements<T, true>(
306 GAIA_ACC((uint8_t*)&m_data[0]), GAIA_ACC((uint8_t*)&other.m_data[0]), other.size(), 0, extent,
309 other.m_cnt = size_type(0);
314 GAIA_CLANG_WARNING_PUSH()
316 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
318 GAIA_NODISCARD
constexpr pointer data()
noexcept {
319 return GAIA_ACC((pointer)&m_data[0]);
322 GAIA_NODISCARD
constexpr const_pointer data()
const noexcept {
323 return GAIA_ACC((const_pointer)&m_data[0]);
326 GAIA_NODISCARD
constexpr decltype(
auto)
operator[](size_type pos)
noexcept {
327 GAIA_ASSERT(pos < size());
328 return view_policy::set({GAIA_ACC((
typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
331 GAIA_NODISCARD
constexpr decltype(
auto)
operator[](size_type pos)
const noexcept {
332 GAIA_ASSERT(pos < size());
333 return view_policy::get({GAIA_ACC((
typename view_policy::TargetCastType) & m_data[0]), extent}, pos);
336 GAIA_CLANG_WARNING_POP()
338 constexpr void push_back(
const T& arg)
noexcept {
339 GAIA_ASSERT(size() < N);
341 operator[](m_cnt++) = arg;
344 constexpr void push_back(T&& arg)
noexcept {
345 GAIA_ASSERT(size() < N);
347 operator[](m_cnt++) = GAIA_MOV(arg);
350 template <
typename... Args>
351 constexpr decltype(
auto) emplace_back(Args&&... args)
noexcept {
352 GAIA_ASSERT(size() < N);
354 operator[](m_cnt++) = T(GAIA_FWD(args)...);
357 constexpr void pop_back()
noexcept {
358 GAIA_ASSERT(!empty());
367 GAIA_ASSERT(size() < N);
368 GAIA_ASSERT(pos >= data());
369 GAIA_ASSERT(empty() || (pos <
iterator(data() + size())));
371 const auto idxSrc = (size_type)core::distance(begin(), pos);
372 const auto idxDst = (size_type)core::distance(begin(), end());
374 mem::shift_elements_right<T, true>(m_data, idxDst, idxSrc, extent);
376 operator[](idxSrc) = arg;
380 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
387 GAIA_ASSERT(size() < N);
388 GAIA_ASSERT(pos >= data());
389 GAIA_ASSERT(empty() || (pos <
iterator(data() + size())));
391 const auto idxSrc = (size_type)core::distance(begin(), pos);
392 const auto idxDst = (size_type)core::distance(begin(), end());
394 mem::shift_elements_right<T, true>(m_data, idxDst, idxSrc, extent);
396 operator[](idxSrc) = GAIA_MOV(arg);
400 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
406 GAIA_ASSERT(pos >= data());
407 GAIA_ASSERT(empty() || (pos <
iterator(data() + size())));
412 const auto idxSrc = (size_type)core::distance(begin(), pos);
413 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
415 mem::shift_elements_left<T, true>(m_data, idxDst, idxSrc, extent);
419 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
426 GAIA_ASSERT(first >= data())
427 GAIA_ASSERT(empty() || (first <
iterator(data() + size())));
428 GAIA_ASSERT(last > first);
429 GAIA_ASSERT(last <= (data() + size()));
434 const auto idxSrc = (size_type)core::distance(begin(), first);
435 const auto idxDst = size();
436 const auto cnt = (size_type)(last - first);
438 mem::shift_elements_left_fast<T, true>(m_data, idxDst, idxSrc, cnt, extent);
442 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
447 GAIA_ASSERT(pos < size());
449 const auto idxSrc = pos;
450 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
452 mem::shift_elements_left<T, true>(m_data, idxDst, idxSrc, extent);
456 return iterator(GAIA_ACC(&m_data[0]), extent, idxSrc);
459 constexpr void clear() noexcept {
463 constexpr void resize(size_type count)
noexcept {
464 GAIA_ASSERT(count <= max_size());
472 template <
typename Func>
474 size_type erased = 0;
475 size_type idxDst = 0;
476 size_type idxSrc = 0;
478 while (idxSrc < m_cnt) {
479 if (func(
operator[](idxSrc))) {
480 if (idxDst < idxSrc) {
481 auto* ptr = (uint8_t*)data();
482 mem::move_element<T, true>(ptr, ptr, idxDst, idxSrc, max_size(), max_size());
483 auto* ptr2 = &data()[idxSrc];
484 core::call_dtor(ptr2);
488 auto* ptr = &data()[idxSrc];
489 core::call_dtor(ptr);
500 GAIA_NODISCARD
constexpr size_type size() const noexcept {
504 GAIA_NODISCARD
constexpr bool empty() const noexcept {
508 GAIA_NODISCARD
constexpr size_type capacity() const noexcept {
512 GAIA_NODISCARD
constexpr size_type max_size() const noexcept {
516 GAIA_NODISCARD
constexpr decltype(
auto) front() noexcept {
517 GAIA_ASSERT(!empty());
521 GAIA_NODISCARD
constexpr decltype(
auto) front() const noexcept {
522 GAIA_ASSERT(!empty());
526 GAIA_NODISCARD
constexpr decltype(
auto) back() noexcept {
527 GAIA_ASSERT(!empty());
528 return (
operator[])(m_cnt - 1);
531 GAIA_NODISCARD
constexpr decltype(
auto) back() const noexcept {
532 GAIA_ASSERT(!empty());
533 return operator[](m_cnt - 1);
536 GAIA_NODISCARD
constexpr auto begin() noexcept {
537 return iterator(GAIA_ACC(&m_data[0]), extent, 0);
540 GAIA_NODISCARD
constexpr auto begin() const noexcept {
541 return const_iterator(GAIA_ACC(&m_data[0]), extent, 0);
544 GAIA_NODISCARD
constexpr auto cbegin() const noexcept {
545 return const_iterator(GAIA_ACC(&m_data[0]), extent, 0);
548 GAIA_NODISCARD
constexpr auto rbegin() noexcept {
549 return iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
552 GAIA_NODISCARD
constexpr auto rbegin() const noexcept {
553 return const_iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
556 GAIA_NODISCARD
constexpr auto crbegin() const noexcept {
557 return const_iterator(GAIA_ACC(&m_data[0]), extent, size() - 1);
560 GAIA_NODISCARD
constexpr auto end() noexcept {
561 return iterator(GAIA_ACC(&m_data[0]), extent, size());
564 GAIA_NODISCARD
constexpr auto end() const noexcept {
565 return const_iterator(GAIA_ACC(&m_data[0]), extent, size());
568 GAIA_NODISCARD
constexpr auto cend() const noexcept {
569 return const_iterator(GAIA_ACC(&m_data[0]), extent, size());
572 GAIA_NODISCARD
constexpr auto rend() noexcept {
573 return iterator(GAIA_ACC(&m_data[0]), extent, -1);
576 GAIA_NODISCARD
constexpr auto rend() const noexcept {
577 return const_iterator(GAIA_ACC(&m_data[0]), extent, -1);
580 GAIA_NODISCARD
constexpr auto crend() const noexcept {
581 return const_iterator(GAIA_ACC(&m_data[0]), extent, -1);
584 GAIA_NODISCARD
constexpr bool operator==(
const sarr_ext_soa& other)
const noexcept {
585 if (m_cnt != other.m_cnt)
587 const size_type n = size();
588 for (size_type i = 0; i < n; ++i)
589 if (!(
operator[](i) == other[i]))
594 GAIA_NODISCARD
constexpr bool operator!=(
const sarr_ext_soa& other)
const noexcept {
595 return !operator==(other);
598 template <
size_t Item>
599 auto view_mut() noexcept {
600 return mem::data_view_policy<T::gaia_Data_Layout, T>::template set<Item>(
604 template <
size_t Item>
605 auto view() const noexcept {
606 return mem::data_view_policy<T::gaia_Data_Layout, T>::template get<Item>(