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;
291 template <
typename InputIt>
293 const auto count = (size_type)core::distance(first, last);
296 if constexpr (std::is_pointer_v<InputIt>) {
297 for (size_type i = 0; i < count; ++i)
298 operator[](i) = first[i];
299 }
else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
300 for (size_type i = 0; i < count; ++i)
301 operator[](i) = *(first[i]);
304 for (
auto it = first; it != last; ++it)
305 operator[](++i) = *it;
314 GAIA_ASSERT(core::addressof(other) !=
this);
317 if (other.m_pDataHeap ==
nullptr) {
318 view_policy::mem_add_block(m_data, extent, other.size());
319 mem::move_elements<T, true>(m_data, other.m_data, other.size(), 0, extent, other.extent);
320 view_policy::mem_del_block(other.m_data, extent, other.size());
321 m_pDataHeap =
nullptr;
324 m_pDataHeap = other.m_pDataHeap;
325 m_pData = m_pDataHeap;
331 other.m_pDataHeap =
nullptr;
332 other.m_pData = other.m_data;
333 other.m_cnt = size_type(0);
334 other.m_cap = extent;
343 GAIA_ASSERT(core::addressof(other) !=
this);
345 resize(other.size());
346 mem::copy_elements<T, true>(
347 (uint8_t*)m_pData, (
const uint8_t*)other.m_pData, other.size(), 0, capacity(), other.capacity());
353 GAIA_ASSERT(core::addressof(other) !=
this);
356 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
359 if (other.m_pDataHeap ==
nullptr) {
360 view_policy::mem_add_block(m_data, extent, other.size());
361 mem::move_elements<T, true>(m_data, other.m_data, other.size(), 0, extent, other.extent);
362 view_policy::mem_del_block(other.m_data, extent, other.size());
363 m_pDataHeap =
nullptr;
366 m_pDataHeap = other.m_pDataHeap;
367 m_pData = m_pDataHeap;
373 other.m_cnt = size_type(0);
374 other.m_cap = extent;
375 other.m_pDataHeap =
nullptr;
376 other.m_pData = other.m_data;
382 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
385 GAIA_CLANG_WARNING_PUSH()
387 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
389 GAIA_NODISCARD pointer data()
noexcept {
390 return reinterpret_cast<pointer
>(m_pData);
393 GAIA_NODISCARD const_pointer data()
const noexcept {
394 return reinterpret_cast<const_pointer
>(m_pData);
397 GAIA_NODISCARD
decltype(
auto)
operator[](size_type pos)
noexcept {
398 GAIA_ASSERT(pos < size());
399 return view_policy::set({(
typename view_policy::TargetCastType)m_pData, size()}, pos);
402 GAIA_NODISCARD
decltype(
auto)
operator[](size_type pos)
const noexcept {
403 GAIA_ASSERT(pos < size());
404 return view_policy::get({(
typename view_policy::TargetCastType)m_pData, size()}, pos);
407 GAIA_CLANG_WARNING_POP()
409 void reserve(size_type cap) {
413 auto* pDataOld = m_pDataHeap;
414 m_pDataHeap = view_policy::template alloc<Allocator>(cap);
415 view_policy::mem_add_block(m_pDataHeap, cap, m_cnt);
417 mem::move_elements<T, true>(m_pDataHeap, pDataOld, m_cnt, 0, cap, m_cap);
418 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
420 m_pDataHeap = view_policy::template alloc<Allocator>(cap);
421 mem::move_elements<T, true>(m_pDataHeap, m_data, m_cnt, 0, cap, m_cap);
425 m_pData = m_pDataHeap;
428 void resize(size_type count) {
434 view_policy::mem_pop_block(data(), m_cap, m_cnt, m_cnt - count);
441 if (count <= m_cap) {
442 view_policy::mem_push_block(data(), m_cap, m_cnt, count - m_cnt);
448 auto* pDataOld = m_pDataHeap;
449 m_pDataHeap = view_policy::template alloc<Allocator>(count);
450 view_policy::mem_add_block(m_pDataHeap, count, count);
451 if (pDataOld !=
nullptr) {
452 mem::move_elements<T, true>(m_pDataHeap, pDataOld, m_cnt, 0, count, m_cap);
453 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
455 mem::move_elements<T, true>(m_pDataHeap, m_data, m_cnt, 0, count, m_cap);
456 view_policy::mem_del_block(m_data, m_cap, m_cnt);
461 m_pData = m_pDataHeap;
464 void push_back(
const T& arg) {
467 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
468 operator[](m_cnt++) = arg;
471 void push_back(T&& arg) {
474 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
475 operator[](m_cnt++) = GAIA_MOV(arg);
478 template <
typename... Args>
479 decltype(
auto) emplace_back(Args&&... args) {
482 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
483 operator[](m_cnt++) = T(GAIA_FWD(args)...);
486 void pop_back()
noexcept {
487 GAIA_ASSERT(!empty());
489 view_policy::mem_pop_block(data(), m_cap, m_cnt, 1);
498 GAIA_ASSERT(pos >= data());
499 GAIA_ASSERT(empty() || (pos <
iterator(data() + size())));
501 const auto idxSrc = (size_type)core::distance(begin(), pos);
503 const auto idxDst = (size_type)core::distance(begin(), end()) + 1;
505 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
506 mem::shift_elements_right<T, true>(m_pData, idxDst, idxSrc, m_cap);
508 operator[](idxSrc) = arg;
512 return iterator(m_pData, capacity(), idxSrc);
519 GAIA_ASSERT(pos >= data());
520 GAIA_ASSERT(empty() || (pos <
iterator(data() + size())));
522 const auto idxSrc = (size_type)core::distance(begin(), pos);
524 const auto idxDst = (size_type)core::distance(begin(), end());
526 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
527 mem::shift_elements_right<T, true>(m_pData, idxDst, idxSrc, m_cap);
529 operator[](idxSrc) = GAIA_MOV(arg);
533 return iterator(m_pData, capacity(), idxSrc);
539 GAIA_ASSERT(pos >= data());
540 GAIA_ASSERT(empty() || (pos <
iterator(data() + size())));
545 const auto idxSrc = (size_type)core::distance(begin(), pos);
546 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
548 mem::shift_elements_left<T, true>(m_pData, idxDst, idxSrc, m_cap);
549 view_policy::mem_pop_block(data(), m_cap, m_cnt, 1);
553 return iterator(m_pData, capacity(), idxSrc);
560 GAIA_ASSERT(first >= data())
561 GAIA_ASSERT(empty() || (first <
iterator(data() + size())));
562 GAIA_ASSERT(last > first);
563 GAIA_ASSERT(last <=
iterator(data() + size()));
568 const auto idxSrc = (size_type)core::distance(begin(), first);
569 const auto idxDst = size();
570 const auto cnt = (size_type)(last - first);
572 mem::shift_elements_left_fast<T, true>(m_pData, idxDst, idxSrc, cnt, m_cap);
573 view_policy::mem_pop_block(data(), m_cap, m_cnt, cnt);
577 return iterator(m_pData, capacity(), idxSrc);
580 void clear() noexcept {
584 void shrink_to_fit() {
585 const auto cap = capacity();
586 const auto cnt = size();
591 if (m_pDataHeap !=
nullptr) {
592 auto* pDataOld = m_pDataHeap;
595 mem::move_elements<T, true>(m_data, pDataOld, cnt, 0);
599 m_pDataHeap = view_policy::template alloc<Allocator>(m_cap = cnt);
600 view_policy::mem_add_block(m_pDataHeap, m_cap, m_cnt);
601 mem::move_elements<T, true>(m_pDataHeap, pDataOld, cnt, 0);
602 m_pData = m_pDataHeap;
605 view_policy::mem_del_block(pDataOld, cap, cnt);
606 view_policy::template free<Allocator>(pDataOld);
614 template <
typename Func>
616 size_type erased = 0;
617 size_type idxDst = 0;
618 size_type idxSrc = 0;
620 while (idxSrc < m_cnt) {
621 if (func(
operator[](idxSrc))) {
622 if (idxDst < idxSrc) {
623 auto* ptr = (uint8_t*)data();
624 mem::move_elements<T, true>(ptr, ptr, idxDst, idxSrc, m_cap, m_cap);
634 view_policy::mem_pop_block(data(), m_cap, m_cnt, erased);
640 GAIA_NODISCARD size_type size() const noexcept {
644 GAIA_NODISCARD
bool empty() const noexcept {
648 GAIA_NODISCARD size_type capacity() const noexcept {
652 GAIA_NODISCARD size_type max_size() const noexcept {
656 GAIA_NODISCARD
decltype(
auto) front() noexcept {
657 GAIA_ASSERT(!empty());
661 GAIA_NODISCARD
decltype(
auto) front() const noexcept {
662 GAIA_ASSERT(!empty());
666 GAIA_NODISCARD
decltype(
auto) back() noexcept {
667 GAIA_ASSERT(!empty());
668 return operator[](m_cnt - 1);
671 GAIA_NODISCARD
decltype(
auto) back() const noexcept {
672 GAIA_ASSERT(!empty());
673 return operator[](m_cnt - 1);
676 GAIA_NODISCARD
auto begin() noexcept {
677 return iterator(m_pData, capacity(), 0);
680 GAIA_NODISCARD
auto begin() const noexcept {
681 return const_iterator(m_pData, capacity(), 0);
684 GAIA_NODISCARD
auto cbegin() const noexcept {
685 return const_iterator(m_pData, capacity(), 0);
688 GAIA_NODISCARD
auto rbegin() noexcept {
689 return iterator(m_pData, capacity(), size() - 1);
692 GAIA_NODISCARD
auto rbegin() const noexcept {
693 return const_iterator(m_pData, capacity(), size() - 1);
696 GAIA_NODISCARD
auto crbegin() const noexcept {
697 return const_iterator(m_pData, capacity(), size() - 1);
700 GAIA_NODISCARD
auto end() noexcept {
701 return iterator(m_pData, capacity(), size());
704 GAIA_NODISCARD
auto end() const noexcept {
705 return const_iterator(m_pData, capacity(), size());
708 GAIA_NODISCARD
auto cend() const noexcept {
709 return const_iterator(m_pData, capacity(), size());
712 GAIA_NODISCARD
auto rend() noexcept {
713 return iterator(m_pData, capacity(), -1);
716 GAIA_NODISCARD
auto rend() const noexcept {
717 return const_iterator(m_pData, capacity(), -1);
720 GAIA_NODISCARD
auto crend() const noexcept {
721 return const_iterator(m_pData, capacity(), -1);
724 GAIA_NODISCARD
bool operator==(
const darr_ext_soa& other)
const noexcept {
725 if (m_cnt != other.m_cnt)
727 const size_type n = size();
728 for (size_type i = 0; i < n; ++i)
729 if (!(
operator[](i) == other[i]))
734 GAIA_NODISCARD
constexpr bool operator!=(
const darr_ext_soa& other)
const noexcept {
735 return !operator==(other);
738 template <
size_t Item>
739 auto view_mut() noexcept {
740 return mem::data_view_policy<T::gaia_Data_Layout, T>::template set<Item>(
744 template <
size_t Item>
745 auto view() const noexcept {
746 return mem::data_view_policy<T::gaia_Data_Layout, T>::template get<Item>(