215 static_assert(mem::is_soa_layout_v<T>,
"darr_ext_soa can be used only with soa types");
218 static_assert(N > 0);
220 using value_type = T;
221 using reference = T&;
222 using const_reference =
const T&;
224 using const_pointer =
const T*;
226 using difference_type = darr_ext_soa_detail::difference_type;
227 using size_type = darr_ext_soa_detail::size_type;
233 static constexpr size_type extent = N;
234 static constexpr uint32_t allocated_bytes = view_policy::get_min_byte_size(0, N);
240 uint8_t* m_pDataHeap =
nullptr;
242 uint8_t* m_pData = m_data;
244 size_type m_cnt = size_type(0);
246 size_type m_cap = extent;
249 const auto cnt = size();
250 const auto cap = capacity();
253 if GAIA_LIKELY (cnt < cap)
258 m_cap = (cap * 3 + 1) / 2;
260 if GAIA_UNLIKELY (m_pDataHeap ==
nullptr) {
262 m_pDataHeap = view_policy::template alloc<Allocator>(m_cap);
263 view_policy::mem_add_block(m_pDataHeap, m_cap, cnt);
264 mem::move_elements<T, true>(m_pDataHeap, m_data, cnt, 0, m_cap, cap);
267 auto* pDataOld = m_pDataHeap;
268 m_pDataHeap = view_policy::template alloc<Allocator>(m_cap);
269 view_policy::mem_add_block(m_pDataHeap, m_cap, cnt);
270 mem::move_elements<T, true>(m_pDataHeap, pDataOld, cnt, 0, m_cap, cap);
271 view_policy::template free<Allocator>(pDataOld, cap, cnt);
274 m_pData = m_pDataHeap;
282 resize(count, value);
289 template <
typename InputIt>
291 const auto count = (size_type)core::distance(first, last);
294 if constexpr (std::is_pointer_v<InputIt>) {
295 for (size_type i = 0; i < count; ++i)
296 operator[](i) = first[i];
297 }
else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
298 for (size_type i = 0; i < count; ++i)
299 operator[](i) = *(first[i]);
302 for (
auto it = first; it != last; ++it)
303 operator[](++i) = *it;
312 GAIA_ASSERT(core::addressof(other) !=
this);
315 if (other.m_pDataHeap ==
nullptr) {
316 view_policy::mem_add_block(m_data, extent, other.size());
317 mem::move_elements<T, true>(m_data, other.m_data, other.size(), 0, extent, other.extent);
318 view_policy::mem_del_block(other.m_data, extent, other.size());
319 m_pDataHeap =
nullptr;
322 m_pDataHeap = other.m_pDataHeap;
323 m_pData = m_pDataHeap;
329 other.m_pDataHeap =
nullptr;
330 other.m_pData = other.m_data;
331 other.m_cnt = size_type(0);
332 other.m_cap = extent;
341 GAIA_ASSERT(core::addressof(other) !=
this);
343 resize(other.size());
344 mem::copy_elements<T, true>(
345 (uint8_t*)m_pData, (
const uint8_t*)other.m_pData, other.size(), 0, capacity(), other.capacity());
351 GAIA_ASSERT(core::addressof(other) !=
this);
354 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
357 if (other.m_pDataHeap ==
nullptr) {
358 view_policy::mem_add_block(m_data, extent, other.size());
359 mem::move_elements<T, true>(m_data, other.m_data, other.size(), 0, extent, other.extent);
360 view_policy::mem_del_block(other.m_data, extent, other.size());
361 m_pDataHeap =
nullptr;
364 m_pDataHeap = other.m_pDataHeap;
365 m_pData = m_pDataHeap;
371 other.m_cnt = size_type(0);
372 other.m_cap = extent;
373 other.m_pDataHeap =
nullptr;
374 other.m_pData = other.m_data;
380 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
383 GAIA_CLANG_WARNING_PUSH()
385 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
387 GAIA_NODISCARD pointer data()
noexcept {
388 return reinterpret_cast<pointer
>(m_pData);
391 GAIA_NODISCARD const_pointer data()
const noexcept {
392 return reinterpret_cast<const_pointer
>(m_pData);
395 GAIA_NODISCARD
decltype(
auto)
operator[](size_type pos)
noexcept {
396 GAIA_ASSERT(pos < size());
397 return view_policy::set({(
typename view_policy::TargetCastType)m_pData, capacity()}, pos);
400 GAIA_NODISCARD
decltype(
auto)
operator[](size_type pos)
const noexcept {
401 GAIA_ASSERT(pos < size());
402 return view_policy::get({(
typename view_policy::TargetCastType)m_pData, capacity()}, pos);
405 GAIA_CLANG_WARNING_POP()
407 void reserve(size_type cap) {
411 auto* pDataOld = m_pDataHeap;
412 m_pDataHeap = view_policy::template alloc<Allocator>(cap);
413 view_policy::mem_add_block(m_pDataHeap, cap, m_cnt);
414 if (pDataOld !=
nullptr) {
415 mem::move_elements<T, true>(m_pDataHeap, pDataOld, m_cnt, 0, cap, m_cap);
416 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
418 mem::move_elements<T, true>(m_pDataHeap, m_data, m_cnt, 0, cap, m_cap);
419 view_policy::mem_del_block(m_data, extent, m_cnt);
423 m_pData = m_pDataHeap;
426 void resize(size_type count) {
432 view_policy::mem_pop_block(data(), m_cap, m_cnt, m_cnt - count);
439 if (count <= m_cap) {
440 view_policy::mem_push_block(data(), m_cap, m_cnt, count - m_cnt);
446 auto* pDataOld = m_pDataHeap;
447 m_pDataHeap = view_policy::template alloc<Allocator>(count);
448 view_policy::mem_add_block(m_pDataHeap, count, count);
449 if (pDataOld !=
nullptr) {
450 mem::move_elements<T, true>(m_pDataHeap, pDataOld, m_cnt, 0, count, m_cap);
451 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
453 mem::move_elements<T, true>(m_pDataHeap, m_data, m_cnt, 0, count, m_cap);
454 view_policy::mem_del_block(m_data, m_cap, m_cnt);
459 m_pData = m_pDataHeap;
462 void resize(size_type count, const_reference value) {
463 const auto oldCount = m_cnt;
466 if constexpr (std::is_copy_constructible_v<value_type>) {
467 const value_type valueCopy = value;
468 for (size_type i = oldCount; i < m_cnt; ++i)
469 operator[](i) = valueCopy;
471 for (size_type i = oldCount; i < m_cnt; ++i)
472 operator[](i) = value;
476 void push_back(
const T& arg) {
479 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
480 operator[](m_cnt++) = arg;
483 void push_back(T&& arg) {
486 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
487 operator[](m_cnt++) = GAIA_MOV(arg);
490 template <
typename... Args>
491 decltype(
auto) emplace_back(Args&&... args) {
494 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
495 operator[](m_cnt++) = T(GAIA_FWD(args)...);
498 void pop_back()
noexcept {
499 GAIA_ASSERT(!empty());
501 view_policy::mem_pop_block(data(), m_cap, m_cnt, 1);
510 GAIA_ASSERT(pos >= data());
511 GAIA_ASSERT(empty() || (pos <
iterator(data() + size())));
513 const auto idxSrc = (size_type)core::distance(begin(), pos);
515 const auto idxDst = (size_type)core::distance(begin(), end()) + 1;
517 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
518 mem::shift_elements_right<T, true>(m_pData, idxDst, idxSrc, m_cap);
520 operator[](idxSrc) = arg;
524 return iterator(m_pData, capacity(), idxSrc);
531 GAIA_ASSERT(pos >= data());
532 GAIA_ASSERT(empty() || (pos <
iterator(data() + size())));
534 const auto idxSrc = (size_type)core::distance(begin(), pos);
536 const auto idxDst = (size_type)core::distance(begin(), end());
538 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
539 mem::shift_elements_right<T, true>(m_pData, idxDst, idxSrc, m_cap);
541 operator[](idxSrc) = GAIA_MOV(arg);
545 return iterator(m_pData, capacity(), idxSrc);
551 GAIA_ASSERT(pos >= data());
552 GAIA_ASSERT(empty() || (pos <
iterator(data() + size())));
557 const auto idxSrc = (size_type)core::distance(begin(), pos);
558 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
560 mem::shift_elements_left<T, true>(m_pData, idxDst, idxSrc, m_cap);
561 view_policy::mem_pop_block(data(), m_cap, m_cnt, 1);
565 return iterator(m_pData, capacity(), idxSrc);
572 GAIA_ASSERT(first >= data())
573 GAIA_ASSERT(empty() || (first <
iterator(data() + size())));
574 GAIA_ASSERT(last > first);
575 GAIA_ASSERT(last <=
iterator(data() + size()));
580 const auto idxSrc = (size_type)core::distance(begin(), first);
581 const auto idxDst = size();
582 const auto cnt = (size_type)(last - first);
584 mem::shift_elements_left_fast<T, true>(m_pData, idxDst, idxSrc, cnt, m_cap);
585 view_policy::mem_pop_block(data(), m_cap, m_cnt, cnt);
589 return iterator(m_pData, capacity(), idxSrc);
592 void clear() noexcept {
596 void shrink_to_fit() {
597 const auto cap = capacity();
598 const auto cnt = size();
603 if (m_pDataHeap !=
nullptr) {
604 auto* pDataOld = m_pDataHeap;
607 mem::move_elements<T, true>(m_data, pDataOld, cnt, 0);
611 m_pDataHeap = view_policy::template alloc<Allocator>(m_cap = cnt);
612 view_policy::mem_add_block(m_pDataHeap, m_cap, m_cnt);
613 mem::move_elements<T, true>(m_pDataHeap, pDataOld, cnt, 0);
614 m_pData = m_pDataHeap;
617 view_policy::mem_del_block(pDataOld, cap, cnt);
618 view_policy::template free<Allocator>(pDataOld);
626 template <
typename Func>
628 size_type erased = 0;
629 size_type idxDst = 0;
630 size_type idxSrc = 0;
632 while (idxSrc < m_cnt) {
633 if (func(
operator[](idxSrc))) {
634 if (idxDst < idxSrc) {
635 auto* ptr = (uint8_t*)data();
636 mem::move_elements<T, true>(ptr, ptr, idxDst, idxSrc, m_cap, m_cap);
646 view_policy::mem_pop_block(data(), m_cap, m_cnt, erased);
652 GAIA_NODISCARD size_type size() const noexcept {
656 GAIA_NODISCARD
bool empty() const noexcept {
660 GAIA_NODISCARD size_type capacity() const noexcept {
664 GAIA_NODISCARD size_type max_size() const noexcept {
668 GAIA_NODISCARD
decltype(
auto) front() noexcept {
669 GAIA_ASSERT(!empty());
673 GAIA_NODISCARD
decltype(
auto) front() const noexcept {
674 GAIA_ASSERT(!empty());
678 GAIA_NODISCARD
decltype(
auto) back() noexcept {
679 GAIA_ASSERT(!empty());
680 return operator[](m_cnt - 1);
683 GAIA_NODISCARD
decltype(
auto) back() const noexcept {
684 GAIA_ASSERT(!empty());
685 return operator[](m_cnt - 1);
688 GAIA_NODISCARD
auto begin() noexcept {
689 return iterator(m_pData, capacity(), 0);
692 GAIA_NODISCARD
auto begin() const noexcept {
693 return const_iterator(m_pData, capacity(), 0);
696 GAIA_NODISCARD
auto cbegin() const noexcept {
697 return const_iterator(m_pData, capacity(), 0);
700 GAIA_NODISCARD
auto rbegin() noexcept {
701 return iterator(m_pData, capacity(), size() - 1);
704 GAIA_NODISCARD
auto rbegin() const noexcept {
705 return const_iterator(m_pData, capacity(), size() - 1);
708 GAIA_NODISCARD
auto crbegin() const noexcept {
709 return const_iterator(m_pData, capacity(), size() - 1);
712 GAIA_NODISCARD
auto end() noexcept {
713 return iterator(m_pData, capacity(), size());
716 GAIA_NODISCARD
auto end() const noexcept {
717 return const_iterator(m_pData, capacity(), size());
720 GAIA_NODISCARD
auto cend() const noexcept {
721 return const_iterator(m_pData, capacity(), size());
724 GAIA_NODISCARD
auto rend() noexcept {
725 return iterator(m_pData, capacity(), -1);
728 GAIA_NODISCARD
auto rend() const noexcept {
729 return const_iterator(m_pData, capacity(), -1);
732 GAIA_NODISCARD
auto crend() const noexcept {
733 return const_iterator(m_pData, capacity(), -1);
736 GAIA_NODISCARD
bool operator==(
const darr_ext_soa& other)
const noexcept {
737 if (m_cnt != other.m_cnt)
739 const size_type n = size();
740 for (size_type i = 0; i < n; ++i)
741 if (!(
operator[](i) == other[i]))
746 GAIA_NODISCARD
constexpr bool operator!=(
const darr_ext_soa& other)
const noexcept {
747 return !operator==(other);
750 template <
size_t Item>
751 auto view_mut() noexcept {
752 return mem::data_view_policy<T::gaia_Data_Layout, T>::template set<Item>(
756 template <
size_t Item>
757 auto view() const noexcept {
758 return mem::data_view_policy<T::gaia_Data_Layout, T>::template get<Item>(