Gaia-ECS v0.9.3
A simple and powerful entity component system
Loading...
Searching...
No Matches
darray_ext_soa_impl.h
1#pragma once
2#include "gaia/config/config.h"
3
4#include <cstddef>
5#include <initializer_list>
6#include <type_traits>
7#include <utility>
8
9#include "gaia/core/iterator.h"
10#include "gaia/core/utility.h"
11#include "gaia/mem/data_layout_policy.h"
12#include "gaia/mem/mem_sani.h"
13#include "gaia/mem/mem_utils.h"
14#include "gaia/mem/raw_data_holder.h"
15
16namespace gaia {
17 namespace cnt {
18 namespace darr_ext_soa_detail {
19 using difference_type = uint32_t;
20 using size_type = uint32_t;
21 } // namespace darr_ext_soa_detail
22
23 template <typename T>
25 using value_type = T;
26 // using pointer = T*; not supported
27 // using reference = T&; not supported
28 using difference_type = darr_ext_soa_detail::difference_type;
29 using size_type = darr_ext_soa_detail::size_type;
30
33
34 private:
35 uint8_t* m_ptr;
36 uint32_t m_cnt;
37 uint32_t m_idx;
38
39 public:
40 darr_ext_soa_iterator(uint8_t* ptr, uint32_t cnt, uint32_t idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
41
42 T operator*() const {
43 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
44 }
45 T operator->() const {
46 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
47 }
48 iterator operator[](size_type offset) const {
49 return iterator(m_ptr, m_cnt, m_idx + offset);
50 }
51
52 iterator& operator+=(size_type diff) {
53 m_idx += diff;
54 return *this;
55 }
56 iterator& operator-=(size_type diff) {
57 m_idx -= diff;
58 return *this;
59 }
60 iterator& operator++() {
61 ++m_idx;
62 return *this;
63 }
64 iterator operator++(int) {
65 iterator temp(*this);
66 ++*this;
67 return temp;
68 }
69 iterator& operator--() {
70 --m_idx;
71 return *this;
72 }
73 iterator operator--(int) {
74 iterator temp(*this);
75 --*this;
76 return temp;
77 }
78
79 iterator operator+(size_type offset) const {
80 return iterator(m_ptr, m_cnt, m_idx + offset);
81 }
82 iterator operator-(size_type offset) const {
83 return iterator(m_ptr, m_cnt, m_idx + offset);
84 }
85 difference_type operator-(const iterator& other) const {
86 GAIA_ASSERT(m_ptr == other.m_ptr);
87 return (difference_type)(m_idx - other.m_idx);
88 }
89
90 GAIA_NODISCARD bool operator==(const iterator& other) const {
91 GAIA_ASSERT(m_ptr == other.m_ptr);
92 return m_idx == other.m_idx;
93 }
94 GAIA_NODISCARD bool operator!=(const iterator& other) const {
95 GAIA_ASSERT(m_ptr == other.m_ptr);
96 return m_idx != other.m_idx;
97 }
98 GAIA_NODISCARD bool operator>(const iterator& other) const {
99 GAIA_ASSERT(m_ptr == other.m_ptr);
100 return m_idx > other.m_idx;
101 }
102 GAIA_NODISCARD bool operator>=(const iterator& other) const {
103 GAIA_ASSERT(m_ptr == other.m_ptr);
104 return m_idx >= other.m_idx;
105 }
106 GAIA_NODISCARD bool operator<(const iterator& other) const {
107 GAIA_ASSERT(m_ptr == other.m_ptr);
108 return m_idx < other.m_idx;
109 }
110 GAIA_NODISCARD bool operator<=(const iterator& other) const {
111 GAIA_ASSERT(m_ptr == other.m_ptr);
112 return m_idx <= other.m_idx;
113 }
114 };
115
116 template <typename T>
118 using value_type = T;
119 // using pointer = T*; not supported
120 // using reference = T&; not supported
121 using difference_type = darr_ext_soa_detail::difference_type;
122 using size_type = darr_ext_soa_detail::size_type;
123
126
127 private:
128 const uint8_t* m_ptr;
129 uint32_t m_cnt;
130 uint32_t m_idx;
131
132 public:
133 const_darr_ext_soa_iterator(const uint8_t* ptr, uint32_t cnt, uint32_t idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
134
135 T operator*() const {
136 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
137 }
138 T operator->() const {
139 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
140 }
141 iterator operator[](size_type offset) const {
142 return iterator(m_ptr, m_cnt, m_idx + offset);
143 }
144
145 iterator& operator+=(size_type diff) {
146 m_idx += diff;
147 return *this;
148 }
149 iterator& operator-=(size_type diff) {
150 m_idx -= diff;
151 return *this;
152 }
153 iterator& operator++() {
154 ++m_idx;
155 return *this;
156 }
157 iterator operator++(int) {
158 iterator temp(*this);
159 ++*this;
160 return temp;
161 }
162 iterator& operator--() {
163 --m_idx;
164 return *this;
165 }
166 iterator operator--(int) {
167 iterator temp(*this);
168 --*this;
169 return temp;
170 }
171
172 iterator operator+(size_type offset) const {
173 return iterator(m_ptr, m_cnt, m_idx + offset);
174 }
175 iterator operator-(size_type offset) const {
176 return iterator(m_ptr, m_cnt, m_idx + offset);
177 }
178 difference_type operator-(const iterator& other) const {
179 GAIA_ASSERT(m_ptr == other.m_ptr);
180 return (difference_type)(m_idx - other.m_idx);
181 }
182
183 GAIA_NODISCARD bool operator==(const iterator& other) const {
184 GAIA_ASSERT(m_ptr == other.m_ptr);
185 return m_idx == other.m_idx;
186 }
187 GAIA_NODISCARD bool operator!=(const iterator& other) const {
188 GAIA_ASSERT(m_ptr == other.m_ptr);
189 return m_idx != other.m_idx;
190 }
191 GAIA_NODISCARD bool operator>(const iterator& other) const {
192 GAIA_ASSERT(m_ptr == other.m_ptr);
193 return m_idx > other.m_idx;
194 }
195 GAIA_NODISCARD bool operator>=(const iterator& other) const {
196 GAIA_ASSERT(m_ptr == other.m_ptr);
197 return m_idx >= other.m_idx;
198 }
199 GAIA_NODISCARD bool operator<(const iterator& other) const {
200 GAIA_ASSERT(m_ptr == other.m_ptr);
201 return m_idx < other.m_idx;
202 }
203 GAIA_NODISCARD bool operator<=(const iterator& other) const {
204 GAIA_ASSERT(m_ptr == other.m_ptr);
205 return m_idx <= other.m_idx;
206 }
207 };
208
213 template <typename T, darr_ext_soa_detail::size_type N, typename Allocator = mem::DefaultAllocatorAdaptor>
215 static_assert(mem::is_soa_layout_v<T>, "darr_ext_soa can be used only with soa types");
216
217 public:
218 static_assert(N > 0);
219
220 using value_type = T;
221 using reference = T&;
222 using const_reference = const T&;
223 using pointer = 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;
228
232
233 static constexpr size_type extent = N;
234 static constexpr uint32_t allocated_bytes = view_policy::get_min_byte_size(0, N);
235
236 private:
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;
247
248 void try_grow() {
249 const auto cnt = size();
250 const auto cap = capacity();
251
252 // Unless we reached the capacity don't do anything
253 if GAIA_LIKELY (cnt < cap)
254 return;
255
256 // We increase the capacity in multiples of 1.5 which is about the golden ratio (1.618).
257 // This means we prefer more frequent allocations over memory fragmentation.
258 m_cap = (cap * 3 + 1) / 2;
259
260 if GAIA_UNLIKELY (m_pDataHeap == nullptr) {
261 // If no heap memory is allocated yet we need to allocate it and move the old stack elements to it
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);
265 } else {
266 // Move items from the old heap array to the new one. Delete the old
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);
272 }
273
274 m_pData = m_pDataHeap;
275 }
276
277 public:
278 darr_ext_soa() noexcept = default;
279 darr_ext_soa(core::zero_t) noexcept {}
280
281 darr_ext_soa(size_type count, const_reference value) {
282 resize(count, value);
283 }
284
285 darr_ext_soa(size_type count) {
286 resize(count);
287 }
288
289 template <typename InputIt>
290 darr_ext_soa(InputIt first, InputIt last) {
291 const auto count = (size_type)core::distance(first, last);
292 resize(count);
293
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]);
300 } else {
301 size_type i = 0;
302 for (auto it = first; it != last; ++it)
303 operator[](++i) = *it;
304 }
305 }
306
307 darr_ext_soa(std::initializer_list<T> il): darr_ext_soa(il.begin(), il.end()) {}
308
309 darr_ext_soa(const darr_ext_soa& other): darr_ext_soa(other.begin(), other.end()) {}
310
311 darr_ext_soa(darr_ext_soa&& other) noexcept {
312 GAIA_ASSERT(core::addressof(other) != this);
313
314 // Moving from stack-allocated source
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;
320 m_pData = m_data;
321 } else {
322 m_pDataHeap = other.m_pDataHeap;
323 m_pData = m_pDataHeap;
324 }
325
326 m_cnt = other.m_cnt;
327 m_cap = other.m_cap;
328
329 other.m_pDataHeap = nullptr;
330 other.m_pData = other.m_data;
331 other.m_cnt = size_type(0);
332 other.m_cap = extent;
333 }
334
335 darr_ext_soa& operator=(std::initializer_list<T> il) {
336 *this = darr_ext_soa(il.begin(), il.end());
337 return *this;
338 }
339
340 darr_ext_soa& operator=(const darr_ext_soa& other) {
341 GAIA_ASSERT(core::addressof(other) != this);
342
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());
346
347 return *this;
348 }
349
350 darr_ext_soa& operator=(darr_ext_soa&& other) noexcept {
351 GAIA_ASSERT(core::addressof(other) != this);
352
353 // Release previously allocated memory if there was anything
354 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
355
356 // Moving from stack-allocated source
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;
362 m_pData = m_data;
363 } else {
364 m_pDataHeap = other.m_pDataHeap;
365 m_pData = m_pDataHeap;
366 }
367
368 m_cnt = other.m_cnt;
369 m_cap = other.m_cap;
370
371 other.m_cnt = size_type(0);
372 other.m_cap = extent;
373 other.m_pDataHeap = nullptr;
374 other.m_pData = other.m_data;
375
376 return *this;
377 }
378
379 ~darr_ext_soa() {
380 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
381 }
382
383 GAIA_CLANG_WARNING_PUSH()
384 // Memory is aligned so we can silence this warning
385 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
386
387 GAIA_NODISCARD pointer data() noexcept {
388 return reinterpret_cast<pointer>(m_pData);
389 }
390
391 GAIA_NODISCARD const_pointer data() const noexcept {
392 return reinterpret_cast<const_pointer>(m_pData);
393 }
394
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);
398 }
399
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);
403 }
404
405 GAIA_CLANG_WARNING_POP()
406
407 void reserve(size_type cap) {
408 if (cap <= m_cap)
409 return;
410
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);
417 } else {
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);
420 }
421
422 m_cap = cap;
423 m_pData = m_pDataHeap;
424 }
425
426 void resize(size_type count) {
427 if (count == m_cnt)
428 return;
429
430 // Resizing to a smaller size
431 if (count < m_cnt) {
432 view_policy::mem_pop_block(data(), m_cap, m_cnt, m_cnt - count);
433
434 m_cnt = count;
435 return;
436 }
437
438 // Resizing to a bigger size but still within allocated capacity
439 if (count <= m_cap) {
440 view_policy::mem_push_block(data(), m_cap, m_cnt, count - m_cnt);
441
442 m_cnt = count;
443 return;
444 }
445
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);
452 } else {
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);
455 }
456
457 m_cap = count;
458 m_cnt = count;
459 m_pData = m_pDataHeap;
460 }
461
462 void resize(size_type count, const_reference value) {
463 const auto oldCount = m_cnt;
464 resize(count);
465
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;
470 } else {
471 for (size_type i = oldCount; i < m_cnt; ++i)
472 operator[](i) = value;
473 }
474 }
475
476 void push_back(const T& arg) {
477 try_grow();
478
479 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
480 operator[](m_cnt++) = arg;
481 }
482
483 void push_back(T&& arg) {
484 try_grow();
485
486 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
487 operator[](m_cnt++) = GAIA_MOV(arg);
488 }
489
490 template <typename... Args>
491 decltype(auto) emplace_back(Args&&... args) {
492 try_grow();
493
494 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
495 operator[](m_cnt++) = T(GAIA_FWD(args)...);
496 }
497
498 void pop_back() noexcept {
499 GAIA_ASSERT(!empty());
500
501 view_policy::mem_pop_block(data(), m_cap, m_cnt, 1);
502
503 --m_cnt;
504 }
505
509 iterator insert(iterator pos, const T& arg) {
510 GAIA_ASSERT(pos >= data());
511 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
512
513 const auto idxSrc = (size_type)core::distance(begin(), pos);
514 try_grow();
515 const auto idxDst = (size_type)core::distance(begin(), end()) + 1;
516
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);
519
520 operator[](idxSrc) = arg;
521
522 ++m_cnt;
523
524 return iterator(m_pData, capacity(), idxSrc);
525 }
526
530 iterator insert(iterator pos, T&& arg) {
531 GAIA_ASSERT(pos >= data());
532 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
533
534 const auto idxSrc = (size_type)core::distance(begin(), pos);
535 try_grow();
536 const auto idxDst = (size_type)core::distance(begin(), end());
537
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);
540
541 operator[](idxSrc) = GAIA_MOV(arg);
542
543 ++m_cnt;
544
545 return iterator(m_pData, capacity(), idxSrc);
546 }
547
550 iterator erase(iterator pos) noexcept {
551 GAIA_ASSERT(pos >= data());
552 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
553
554 if (empty())
555 return end();
556
557 const auto idxSrc = (size_type)core::distance(begin(), pos);
558 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
559
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);
562
563 --m_cnt;
564
565 return iterator(m_pData, capacity(), idxSrc);
566 }
567
571 iterator erase(iterator first, iterator last) noexcept {
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()));
576
577 if (empty())
578 return end();
579
580 const auto idxSrc = (size_type)core::distance(begin(), first);
581 const auto idxDst = size();
582 const auto cnt = (size_type)(last - first);
583
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);
586
587 m_cnt -= cnt;
588
589 return iterator(m_pData, capacity(), idxSrc);
590 }
591
592 void clear() noexcept {
593 resize(0);
594 }
595
596 void shrink_to_fit() {
597 const auto cap = capacity();
598 const auto cnt = size();
599
600 if (cap == cnt)
601 return;
602
603 if (m_pDataHeap != nullptr) {
604 auto* pDataOld = m_pDataHeap;
605
606 if (cnt < extent) {
607 mem::move_elements<T, true>(m_data, pDataOld, cnt, 0);
608 m_pData = m_data;
609 m_cap = extent;
610 } else {
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;
615 }
616
617 view_policy::mem_del_block(pDataOld, cap, cnt);
618 view_policy::template free<Allocator>(pDataOld);
619 } else
620 resize(cnt);
621 }
622
626 template <typename Func>
627 auto retain(Func&& func) noexcept {
628 size_type erased = 0;
629 size_type idxDst = 0;
630 size_type idxSrc = 0;
631
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);
637 }
638 ++idxDst;
639 } else {
640 ++erased;
641 }
642
643 ++idxSrc;
644 }
645
646 view_policy::mem_pop_block(data(), m_cap, m_cnt, erased);
647
648 m_cnt -= erased;
649 return idxDst;
650 }
651
652 GAIA_NODISCARD size_type size() const noexcept {
653 return m_cnt;
654 }
655
656 GAIA_NODISCARD bool empty() const noexcept {
657 return size() == 0;
658 }
659
660 GAIA_NODISCARD size_type capacity() const noexcept {
661 return m_cap;
662 }
663
664 GAIA_NODISCARD size_type max_size() const noexcept {
665 return N;
666 }
667
668 GAIA_NODISCARD decltype(auto) front() noexcept {
669 GAIA_ASSERT(!empty());
670 return *begin();
671 }
672
673 GAIA_NODISCARD decltype(auto) front() const noexcept {
674 GAIA_ASSERT(!empty());
675 return *begin();
676 }
677
678 GAIA_NODISCARD decltype(auto) back() noexcept {
679 GAIA_ASSERT(!empty());
680 return operator[](m_cnt - 1);
681 }
682
683 GAIA_NODISCARD decltype(auto) back() const noexcept {
684 GAIA_ASSERT(!empty());
685 return operator[](m_cnt - 1);
686 }
687
688 GAIA_NODISCARD auto begin() noexcept {
689 return iterator(m_pData, capacity(), 0);
690 }
691
692 GAIA_NODISCARD auto begin() const noexcept {
693 return const_iterator(m_pData, capacity(), 0);
694 }
695
696 GAIA_NODISCARD auto cbegin() const noexcept {
697 return const_iterator(m_pData, capacity(), 0);
698 }
699
700 GAIA_NODISCARD auto rbegin() noexcept {
701 return iterator(m_pData, capacity(), size() - 1);
702 }
703
704 GAIA_NODISCARD auto rbegin() const noexcept {
705 return const_iterator(m_pData, capacity(), size() - 1);
706 }
707
708 GAIA_NODISCARD auto crbegin() const noexcept {
709 return const_iterator(m_pData, capacity(), size() - 1);
710 }
711
712 GAIA_NODISCARD auto end() noexcept {
713 return iterator(m_pData, capacity(), size());
714 }
715
716 GAIA_NODISCARD auto end() const noexcept {
717 return const_iterator(m_pData, capacity(), size());
718 }
719
720 GAIA_NODISCARD auto cend() const noexcept {
721 return const_iterator(m_pData, capacity(), size());
722 }
723
724 GAIA_NODISCARD auto rend() noexcept {
725 return iterator(m_pData, capacity(), -1);
726 }
727
728 GAIA_NODISCARD auto rend() const noexcept {
729 return const_iterator(m_pData, capacity(), -1);
730 }
731
732 GAIA_NODISCARD auto crend() const noexcept {
733 return const_iterator(m_pData, capacity(), -1);
734 }
735
736 GAIA_NODISCARD bool operator==(const darr_ext_soa& other) const noexcept {
737 if (m_cnt != other.m_cnt)
738 return false;
739 const size_type n = size();
740 for (size_type i = 0; i < n; ++i)
741 if (!(operator[](i) == other[i]))
742 return false;
743 return true;
744 }
745
746 GAIA_NODISCARD constexpr bool operator!=(const darr_ext_soa& other) const noexcept {
747 return !operator==(other);
748 }
749
750 template <size_t Item>
751 auto view_mut() noexcept {
752 return mem::data_view_policy<T::gaia_Data_Layout, T>::template set<Item>(
753 std::span<uint8_t>{GAIA_ACC((uint8_t*)m_pData), capacity()});
754 }
755
756 template <size_t Item>
757 auto view() const noexcept {
758 return mem::data_view_policy<T::gaia_Data_Layout, T>::template get<Item>(
759 std::span<const uint8_t>{GAIA_ACC((const uint8_t*)m_pData), capacity()});
760 }
761 };
762
763 namespace detail {
764 template <typename T, uint32_t N, uint32_t... I>
765 darr_ext_soa<std::remove_cv_t<T>, N> to_sarray_impl(T (&a)[N], std::index_sequence<I...> /*no_name*/) {
766 return {{a[I]...}};
767 }
768 } // namespace detail
769
770 template <typename T, uint32_t N>
771 darr_ext_soa<std::remove_cv_t<T>, N> to_sarray(T (&a)[N]) {
772 return detail::to_sarray_impl(a, std::make_index_sequence<N>{});
773 }
774
775 } // namespace cnt
776
777} // namespace gaia
Array of elements of type.
Definition darray_ext_soa_impl.h:214
auto retain(Func &&func) noexcept
Removes all elements that fail the predicate.
Definition darray_ext_soa_impl.h:627
iterator insert(iterator pos, T &&arg)
Insert the element to the position given by iterator pos.
Definition darray_ext_soa_impl.h:530
iterator erase(iterator first, iterator last) noexcept
Removes the elements in the range [first, last)
Definition darray_ext_soa_impl.h:571
iterator insert(iterator pos, const T &arg)
Insert the element to the position given by iterator pos.
Definition darray_ext_soa_impl.h:509
iterator erase(iterator pos) noexcept
Removes the element at pos.
Definition darray_ext_soa_impl.h:550
Definition span_impl.h:99
Checks if endianess was detected correctly at compile-time.
Definition bitset.h:9
Definition darray_ext_soa_impl.h:117
Definition darray_ext_soa_impl.h:24
Definition utility.h:87
View policy for accessing and storing data in the SoA way. Good for SIMD processing.
Definition data_layout_policy.h:243
Definition data_layout_policy.h:87
Definition raw_data_holder.h:12