Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
darray_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
15namespace gaia {
16 namespace cnt {
18 namespace darr_soa_detail {
19 using difference_type = uint32_t;
20 using size_type = uint32_t;
21 } // namespace darr_soa_detail
23
25 template <typename T>
26 struct darr_soa_iterator {
28 using value_type = T;
29 // using pointer = T*; not supported
30 // using reference = T&; not supported
32 using difference_type = darr_soa_detail::difference_type;
34 using size_type = darr_soa_detail::size_type;
35
36 using iterator = darr_soa_iterator;
38 using iterator_category = core::random_access_iterator_tag;
39
40 private:
41 uint8_t* m_ptr;
42 uint32_t m_cnt;
43 uint32_t m_idx;
44
45 public:
46 darr_soa_iterator(uint8_t* ptr, uint32_t cnt, uint32_t idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
47
48 T operator*() const {
49 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
50 }
51 T operator->() const {
52 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
53 }
54 iterator operator[](size_type offset) const {
55 return iterator(m_ptr, m_cnt, m_idx + offset);
56 }
57
58 iterator& operator+=(size_type diff) {
59 m_idx += diff;
60 return *this;
61 }
62 iterator& operator-=(size_type diff) {
63 m_idx -= diff;
64 return *this;
65 }
66 iterator& operator++() {
67 ++m_idx;
68 return *this;
69 }
70 iterator operator++(int) {
71 iterator temp(*this);
72 ++*this;
73 return temp;
74 }
75 iterator& operator--() {
76 --m_idx;
77 return *this;
78 }
79 iterator operator--(int) {
80 iterator temp(*this);
81 --*this;
82 return temp;
83 }
84
85 iterator operator+(size_type offset) const {
86 return iterator(m_ptr, m_cnt, m_idx + offset);
87 }
88 iterator operator-(size_type offset) const {
89 return iterator(m_ptr, m_cnt, m_idx + offset);
90 }
91 difference_type operator-(const iterator& other) const {
92 GAIA_ASSERT(m_ptr == other.m_ptr);
93 return (difference_type)(m_idx - other.m_idx);
94 }
95
96 GAIA_NODISCARD bool operator==(const iterator& other) const {
97 GAIA_ASSERT(m_ptr == other.m_ptr);
98 return m_idx == other.m_idx;
99 }
100 GAIA_NODISCARD bool operator!=(const iterator& other) const {
101 GAIA_ASSERT(m_ptr == other.m_ptr);
102 return m_idx != other.m_idx;
103 }
104 GAIA_NODISCARD bool operator>(const iterator& other) const {
105 GAIA_ASSERT(m_ptr == other.m_ptr);
106 return m_idx > other.m_idx;
107 }
108 GAIA_NODISCARD bool operator>=(const iterator& other) const {
109 GAIA_ASSERT(m_ptr == other.m_ptr);
110 return m_idx >= other.m_idx;
111 }
112 GAIA_NODISCARD bool operator<(const iterator& other) const {
113 GAIA_ASSERT(m_ptr == other.m_ptr);
114 return m_idx < other.m_idx;
115 }
116 GAIA_NODISCARD bool operator<=(const iterator& other) const {
117 GAIA_ASSERT(m_ptr == other.m_ptr);
118 return m_idx <= other.m_idx;
119 }
120 };
121
122 template <typename T>
123 struct const_darr_soa_iterator {
124 using value_type = T;
125 // using pointer = T*; not supported
126 // using reference = T&; not supported
127 using difference_type = darr_soa_detail::difference_type;
128 using size_type = darr_soa_detail::size_type;
129
130 using iterator = const_darr_soa_iterator;
131 using iterator_category = core::random_access_iterator_tag;
132
133 private:
134 const uint8_t* m_ptr;
135 uint32_t m_cnt;
136 uint32_t m_idx;
137
138 public:
139 const_darr_soa_iterator(const uint8_t* ptr, uint32_t cnt, uint32_t idx): m_ptr(ptr), m_cnt(cnt), m_idx(idx) {}
140
141 T operator*() const {
142 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
143 }
144 T operator->() const {
145 return mem::data_view_policy<T::gaia_Data_Layout, T>::get({m_ptr, m_cnt}, m_idx);
146 }
147 iterator operator[](size_type offset) const {
148 return iterator(m_ptr, m_cnt, m_idx + offset);
149 }
150
151 iterator& operator+=(size_type diff) {
152 m_idx += diff;
153 return *this;
154 }
155 iterator& operator-=(size_type diff) {
156 m_idx -= diff;
157 return *this;
158 }
159 iterator& operator++() {
160 ++m_idx;
161 return *this;
162 }
163 iterator operator++(int) {
164 iterator temp(*this);
165 ++*this;
166 return temp;
167 }
168 iterator& operator--() {
169 --m_idx;
170 return *this;
171 }
172 iterator operator--(int) {
173 iterator temp(*this);
174 --*this;
175 return temp;
176 }
177
178 iterator operator+(size_type offset) const {
179 return iterator(m_ptr, m_cnt, m_idx + offset);
180 }
181 iterator operator-(size_type offset) const {
182 return iterator(m_ptr, m_cnt, m_idx + offset);
183 }
184 difference_type operator-(const iterator& other) const {
185 GAIA_ASSERT(m_ptr == other.m_ptr);
186 return (difference_type)(m_idx - other.m_idx);
187 }
188
189 GAIA_NODISCARD bool operator==(const iterator& other) const {
190 GAIA_ASSERT(m_ptr == other.m_ptr);
191 return m_idx == other.m_idx;
192 }
193 GAIA_NODISCARD bool operator!=(const iterator& other) const {
194 GAIA_ASSERT(m_ptr == other.m_ptr);
195 return m_idx != other.m_idx;
196 }
197 GAIA_NODISCARD bool operator>(const iterator& other) const {
198 GAIA_ASSERT(m_ptr == other.m_ptr);
199 return m_idx > other.m_idx;
200 }
201 GAIA_NODISCARD bool operator>=(const iterator& other) const {
202 GAIA_ASSERT(m_ptr == other.m_ptr);
203 return m_idx >= other.m_idx;
204 }
205 GAIA_NODISCARD bool operator<(const iterator& other) const {
206 GAIA_ASSERT(m_ptr == other.m_ptr);
207 return m_idx < other.m_idx;
208 }
209 GAIA_NODISCARD bool operator<=(const iterator& other) const {
210 GAIA_ASSERT(m_ptr == other.m_ptr);
211 return m_idx <= other.m_idx;
212 }
213 };
215
219 template <typename T, typename Allocator = mem::DefaultAllocatorAdaptor>
220 class darr_soa {
221 static_assert(mem::is_soa_layout_v<T>, "darr_soa can be used only with soa types");
222
223 public:
225 using value_type = T;
227 using reference = T&;
229 using const_reference = const T&;
231 using pointer = T*;
233 using const_pointer = const T*;
237 using difference_type = darr_soa_detail::difference_type;
239 using size_type = darr_soa_detail::size_type;
240
247
248 private:
249 uint8_t* m_pData = nullptr;
250 size_type m_cnt = size_type(0);
251 size_type m_cap = size_type(0);
252
253 void try_grow() {
254 const auto cnt = size();
255 const auto cap = capacity();
256
257 // Unless we reached the capacity don't do anything
258 if GAIA_LIKELY (cap != 0 && cnt < cap)
259 return;
260
261 // If no data is allocated go with at least 4 elements
262 if GAIA_UNLIKELY (m_pData == nullptr) {
263 m_pData = view_policy::template alloc<Allocator>(m_cap = 4);
264 return;
265 }
266
267 // We increase the capacity in multiples of 1.5 which is about the golden ratio (1.618).
268 // This effectively means we prefer more frequent allocations over memory fragmentation.
269 m_cap = (cap * 3 + 1) / 2;
270
271 auto* pDataOld = m_pData;
272 m_pData = view_policy::template alloc<Allocator>(m_cap);
273 view_policy::mem_add_block(m_pData, m_cap, cnt);
274 mem::move_elements<T, true>(m_pData, pDataOld, cnt, 0, m_cap, cap);
275 view_policy::template free<Allocator>(pDataOld, cap, cnt);
276 }
277
278 public:
279 darr_soa() noexcept = default;
281 darr_soa(core::zero_t) noexcept {}
282
287 resize(count, value);
288 }
289
293 resize(count);
294 }
295
300 template <typename InputIt>
301 darr_soa(InputIt first, InputIt last) {
302 const auto count = (size_type)core::distance(first, last);
303 resize(count);
304
305 if constexpr (std::is_pointer_v<InputIt>) {
306 for (size_type i = 0; i < count; ++i)
307 operator[](i) = first[i];
308 } else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
309 for (size_type i = 0; i < count; ++i)
310 operator[](i) = *(first[i]);
311 } else {
312 size_type i = 0;
313 for (auto it = first; it != last; ++it)
314 operator[](++i) = *it;
315 }
316 }
317
320 darr_soa(std::initializer_list<T> il): darr_soa(il.begin(), il.end()) {}
321
324 darr_soa(const darr_soa& other): darr_soa(other.begin(), other.end()) {}
325
328 darr_soa(darr_soa&& other) noexcept {
329 // This is a newly constructed object.
330 // It can't have any memory allocated, yet.
331 GAIA_ASSERT(m_pData == nullptr);
332
333 m_pData = other.m_pData;
334 m_cnt = other.m_cnt;
335 m_cap = other.m_cap;
336
337 other.m_cnt = size_type(0);
338 other.m_cap = size_type(0);
339 other.m_pData = nullptr;
340 }
341
345 darr_soa& operator=(std::initializer_list<T> il) {
346 *this = darr_soa(il.begin(), il.end());
347 return *this;
348 }
349
353 darr_soa& operator=(const darr_soa& other) {
354 GAIA_ASSERT(core::addressof(other) != this);
355
356 resize(other.size());
357 mem::copy_elements<T, true>(
358 (uint8_t*)m_pData, (const uint8_t*)other.m_pData, other.size(), 0, capacity(), other.capacity());
359
360 return *this;
361 }
362
366 darr_soa& operator=(darr_soa&& other) noexcept {
367 GAIA_ASSERT(core::addressof(other) != this);
368
369 // Release previously allocated memory if there was anything
370 view_policy::template free<Allocator>(m_pData, m_cap, m_cnt);
371
372 m_pData = other.m_pData;
373 m_cnt = other.m_cnt;
374 m_cap = other.m_cap;
375
376 other.m_pData = nullptr;
377 other.m_cnt = size_type(0);
378 other.m_cap = size_type(0);
379
380 return *this;
381 }
382
383 ~darr_soa() {
384 view_policy::template free<Allocator>(m_pData, m_cap, m_cnt);
385 }
386
387 GAIA_CLANG_WARNING_PUSH()
388 // Memory is aligned so we can silence this warning
389 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
390
393 GAIA_NODISCARD pointer data() noexcept {
394 return reinterpret_cast<pointer>(m_pData);
395 }
396
399 GAIA_NODISCARD const_pointer data() const noexcept {
400 return reinterpret_cast<const_pointer>(m_pData);
401 }
402
406 GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept {
407 GAIA_ASSERT(pos < size());
408 return view_policy::set({(typename view_policy::TargetCastType)m_pData, capacity()}, pos);
409 }
410
414 GAIA_NODISCARD decltype(auto) operator[](size_type pos) const noexcept {
415 GAIA_ASSERT(pos < size());
416 return view_policy::get({(typename view_policy::TargetCastType)m_pData, capacity()}, pos);
417 }
418
419 GAIA_CLANG_WARNING_POP()
420
421
424 if (cap <= m_cap)
425 return;
426
427 auto* pDataOld = m_pData;
428 m_pData = view_policy::template alloc<Allocator>(cap);
429
430 if (pDataOld != nullptr) {
431 view_policy::mem_add_block(m_pData, cap, m_cnt);
432 mem::move_elements<T, true>(m_pData, pDataOld, m_cnt, 0, cap, m_cap);
433 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
434 }
435
436 m_cap = cap;
437 }
438
441 void resize(size_type count) {
442 if (count == m_cnt)
443 return;
444
445 // Fresh allocation
446 if (m_pData == nullptr) {
447 if (count > 0) {
448 m_pData = view_policy::template alloc<Allocator>(count);
449 view_policy::mem_add_block(m_pData, count, count);
450 m_cap = count;
451 m_cnt = count;
452 }
453 return;
454 }
455
456 // Resizing to a smaller size
457 if (count < m_cnt) {
458 view_policy::mem_pop_block(m_pData, m_cap, m_cnt, m_cnt - count);
459
460 m_cnt = count;
461 return;
462 }
463
464 // Resizing to a bigger size but still within allocated capacity
465 if (count <= m_cap) {
466 view_policy::mem_pop_block(m_pData, m_cap, m_cnt, count - m_cnt);
467
468 m_cnt = count;
469 return;
470 }
471
472 auto* pDataOld = m_pData;
473 m_pData = view_policy::template alloc<Allocator>(count);
474 view_policy::mem_add_block(m_pData, count, count);
475 // Move old data to the new location
476 mem::move_elements<T, true>(m_pData, pDataOld, m_cnt, 0, count, m_cap);
477 // Release old memory
478 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
479
480 m_cap = count;
481 m_cnt = count;
482 }
483
487 void resize(size_type count, const_reference value) {
488 const auto oldCount = m_cnt;
489 resize(count);
490
491 if constexpr (std::is_copy_constructible_v<value_type>) {
492 const value_type valueCopy = value;
493 for (size_type i = oldCount; i < m_cnt; ++i)
494 operator[](i) = valueCopy;
495 } else {
496 for (size_type i = oldCount; i < m_cnt; ++i)
497 operator[](i) = value;
498 }
499 }
500
503 void push_back(const T& arg) {
504 try_grow();
505
506 operator[](m_cnt++) = arg;
507 }
508
511 void push_back(T&& arg) {
512 try_grow();
513
514 view_policy::mem_push_block(m_pData, m_cap, m_cnt, 1);
515 operator[](m_cnt++) = GAIA_MOV(arg);
516 }
517
522 template <typename... Args>
523 decltype(auto) emplace_back(Args&&... args) {
524 try_grow();
525
526 view_policy::mem_push_block(m_pData, m_cap, m_cnt, 1);
527 operator[](m_cnt++) = T(GAIA_FWD(args)...);
528 }
529
532 GAIA_ASSERT(!empty());
533
534 view_policy::mem_pop_block(m_pData, m_cap, m_cnt, 1);
535
536 --m_cnt;
537 }
538
544 GAIA_ASSERT(pos >= data());
545 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
546
547 const auto idxSrc = (size_type)core::distance(begin(), pos);
548 try_grow();
549 const auto idxDst = (size_type)core::distance(begin(), end()) + 1;
550
551 view_policy::mem_push_block(m_pData, m_cap, m_cnt, 1);
552 mem::shift_elements_right<T, true>(m_pData, idxDst, idxSrc, m_cap);
553
555
556 ++m_cnt;
557
558 return iterator(m_pData, capacity(), idxSrc);
559 }
560
566 GAIA_ASSERT(pos >= data());
567 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
568
569 const auto idxSrc = (size_type)core::distance(begin(), pos);
570 try_grow();
571 const auto idxDst = (size_type)core::distance(begin(), end());
572
573 view_policy::mem_push_block(m_pData, m_cap, m_cnt, 1);
574 mem::shift_elements_right<T, true>(m_pData, idxDst, idxSrc, m_cap);
575
576 operator[](idxSrc) = GAIA_MOV(arg);
577
578 ++m_cnt;
579
580 return iterator(m_pData, capacity(), idxSrc);
581 }
582
587 GAIA_ASSERT(pos >= data());
588 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
589
590 if (empty())
591 return end();
592
593 const auto idxSrc = (size_type)core::distance(begin(), pos);
594 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
595
596 mem::shift_elements_left<T, true>(m_pData, idxDst, idxSrc, m_cap);
597 view_policy::mem_pop_block(m_pData, m_cap, m_cnt, 1);
598
599 --m_cnt;
600
601 return iterator(m_pData, capacity(), idxSrc);
602 }
603
608 iterator erase(iterator first, iterator last) noexcept {
609 GAIA_ASSERT(first >= data())
610 GAIA_ASSERT(empty() || (first < iterator(data() + size())));
611 GAIA_ASSERT(last > first);
612 GAIA_ASSERT(last <= iterator(data() + size()));
613
614 if (empty())
615 return end();
616
617 const auto idxSrc = (size_type)core::distance(begin(), first);
618 const auto idxDst = size();
619 const auto cnt = (size_type)(last - first);
620
621 mem::shift_elements_left_fast<T, true>(m_pData, idxDst, idxSrc, cnt, m_cap);
622 view_policy::mem_pop_block(m_pData, m_cap, m_cnt, cnt);
623
624 m_cnt -= cnt;
625
626 return iterator(&data()[idxSrc]);
627 }
628
631 resize(0);
632 }
633
636 const auto cap = capacity();
637 const auto cnt = size();
638
639 if (cap == cnt)
640 return;
641
642 auto* pDataOld = m_pData;
643 m_pData = view_policy::template alloc<Allocator>(m_cap = cnt);
644 view_policy::mem_add_block(m_pData, m_cap, m_cnt);
645 mem::move_elements<T, true>(m_pData, pDataOld, cnt, 0);
646 view_policy::template free<Allocator>(pDataOld, cap, cnt);
647 }
648
653 template <typename Func>
654 auto retain(Func&& func) noexcept {
655 size_type erased = 0;
656 size_type idxDst = 0;
657 size_type idxSrc = 0;
658
659 while (idxSrc < m_cnt) {
660 if (func(operator[](idxSrc))) {
661 if (idxDst < idxSrc) {
662 mem::move_element<T, true>(m_pData, m_pData, idxDst, idxSrc, m_cap, m_cap);
663 auto* ptr = &data()[idxSrc];
664 core::call_dtor(ptr);
665 }
666 ++idxDst;
667 } else {
668 auto* ptr = &data()[idxSrc];
669 core::call_dtor(ptr);
670 ++erased;
671 }
672
673 ++idxSrc;
674 }
675
676 view_policy::mem_pop_block(m_pData, m_cap, m_cnt, erased);
677
678 m_cnt -= erased;
679 return idxDst;
680 }
681
684 GAIA_NODISCARD size_type size() const noexcept {
685 return m_cnt;
686 }
687
690 GAIA_NODISCARD bool empty() const noexcept {
691 return size() == 0;
692 }
693
696 GAIA_NODISCARD size_type capacity() const noexcept {
697 return m_cap;
698 }
699
702 GAIA_NODISCARD size_type max_size() const noexcept {
703 return static_cast<size_type>(-1);
704 }
705
708 GAIA_NODISCARD decltype(auto) front() noexcept {
709 GAIA_ASSERT(!empty());
710 return *begin();
711 }
712
715 GAIA_NODISCARD decltype(auto) front() const noexcept {
716 GAIA_ASSERT(!empty());
717 return *begin();
718 }
719
722 GAIA_NODISCARD decltype(auto) back() noexcept {
723 GAIA_ASSERT(!empty());
724 return operator[](m_cnt - 1);
725 }
726
729 GAIA_NODISCARD decltype(auto) back() const noexcept {
730 GAIA_ASSERT(!empty());
731 return operator[](m_cnt - 1);
732 }
733
736 GAIA_NODISCARD auto begin() noexcept {
737 return iterator(m_pData, capacity(), 0);
738 }
739
742 GAIA_NODISCARD auto begin() const noexcept {
743 return const_iterator(m_pData, capacity(), 0);
744 }
745
748 GAIA_NODISCARD auto cbegin() const noexcept {
749 return const_iterator(m_pData, capacity(), 0);
750 }
751
754 GAIA_NODISCARD auto rbegin() noexcept {
755 return iterator(m_pData, capacity(), size() - 1);
756 }
757
760 GAIA_NODISCARD auto rbegin() const noexcept {
761 return const_iterator(m_pData, capacity(), size() - 1);
762 }
763
766 GAIA_NODISCARD auto crbegin() const noexcept {
767 return const_iterator(m_pData, capacity(), size() - 1);
768 }
769
772 GAIA_NODISCARD auto end() noexcept {
773 return iterator(m_pData, capacity(), size());
774 }
775
778 GAIA_NODISCARD auto end() const noexcept {
779 return const_iterator(m_pData, capacity(), size());
780 }
781
784 GAIA_NODISCARD auto cend() const noexcept {
785 return const_iterator(m_pData, capacity(), size());
786 }
787
790 GAIA_NODISCARD auto rend() noexcept {
791 return iterator(m_pData, capacity(), -1);
792 }
793
796 GAIA_NODISCARD auto rend() const noexcept {
797 return const_iterator(m_pData, capacity(), -1);
798 }
799
802 GAIA_NODISCARD auto crend() const noexcept {
803 return const_iterator(m_pData, capacity(), -1);
804 }
805
809 GAIA_NODISCARD bool operator==(const darr_soa& other) const noexcept {
810 if (m_cnt != other.m_cnt)
811 return false;
812 const size_type n = size();
813 for (size_type i = 0; i < n; ++i)
814 if (!(operator[](i) == other[i]))
815 return false;
816 return true;
817 }
818
822 GAIA_NODISCARD constexpr bool operator!=(const darr_soa& other) const noexcept {
823 return !operator==(other);
824 }
825
829 template <size_t Item>
832 std::span<uint8_t>{GAIA_ACC((uint8_t*)m_pData), capacity()});
833 }
834
838 template <size_t Item>
841 std::span<const uint8_t>{GAIA_ACC((const uint8_t*)m_pData), capacity()});
842 }
843 };
844 } // namespace cnt
845
846} // namespace gaia
Array with variable size of elements of type.
Definition darray_soa_impl.h:220
iterator insert(iterator pos, T &&arg)
Insert the element to the position given by iterator pos.
Definition darray_soa_impl.h:565
auto view_mut() noexcept
Returns a mutable view of one structure-of-arrays member.
Definition darray_soa_impl.h:830
GAIA_NODISCARD const_pointer data() const noexcept
Returns a pointer to the element storage.
Definition darray_soa_impl.h:399
GAIA_NODISCARD bool empty() const noexcept
Checks whether the container has no elements.
Definition darray_soa_impl.h:690
void reserve(size_type cap)
Ensures storage for at least the requested number of elements.
Definition darray_soa_impl.h:423
void push_back(T &&arg)
Appends an element.
Definition darray_soa_impl.h:511
decltype(auto) emplace_back(Args &&... args)
Constructs and appends an element.
Definition darray_soa_impl.h:523
auto view() const noexcept
Returns a read-only view of one structure-of-arrays member.
Definition darray_soa_impl.h:839
GAIA_NODISCARD auto rbegin() const noexcept
Returns a reverse traversal iterator to the last element.
Definition darray_soa_impl.h:760
darr_soa(const darr_soa &other)
Copy-constructs a container.
Definition darray_soa_impl.h:324
GAIA_NODISCARD auto crbegin() const noexcept
Returns a read-only reverse traversal iterator to the last element.
Definition darray_soa_impl.h:766
GAIA_NODISCARD auto rend() const noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition darray_soa_impl.h:796
void clear() noexcept
Removes all elements.
Definition darray_soa_impl.h:630
GAIA_NODISCARD bool operator==(const darr_soa &other) const noexcept
Compares two containers element by element.
Definition darray_soa_impl.h:809
GAIA_NODISCARD auto cend() const noexcept
Returns a read-only iterator one past the last element.
Definition darray_soa_impl.h:784
const_darr_soa_iterator< T > const_iterator
Read-only random-access iterator type.
Definition darray_soa_impl.h:244
darr_soa_detail::size_type size_type
Unsigned type used for sizes and indices.
Definition darray_soa_impl.h:239
darr_soa_detail::difference_type difference_type
Type used for iterator differences.
Definition darray_soa_impl.h:237
auto retain(Func &&func) noexcept
Removes all elements that fail the predicate.
Definition darray_soa_impl.h:654
GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept
Accesses an element without bounds checking in optimized builds.
Definition darray_soa_impl.h:406
void resize(size_type count, const_reference value)
Changes the size and initializes new elements from a value.
Definition darray_soa_impl.h:487
darr_soa & operator=(darr_soa &&other) noexcept
Move-assigns the container.
Definition darray_soa_impl.h:366
void resize(size_type count)
Changes the number of elements.
Definition darray_soa_impl.h:441
GAIA_NODISCARD size_type capacity() const noexcept
Returns the number of elements that fit without reallocation.
Definition darray_soa_impl.h:696
GAIA_NODISCARD auto end() const noexcept
Returns an iterator one past the last element.
Definition darray_soa_impl.h:778
iterator erase(iterator first, iterator last) noexcept
Removes the elements in the range [first, last)
Definition darray_soa_impl.h:608
GAIA_NODISCARD decltype(auto) front() const noexcept
Accesses the first element.
Definition darray_soa_impl.h:715
GAIA_NODISCARD auto cbegin() const noexcept
Returns a read-only iterator to the first element.
Definition darray_soa_impl.h:748
darr_soa(size_type count, const_reference value)
Constructs a container with copies of a value.
Definition darray_soa_impl.h:286
GAIA_NODISCARD decltype(auto) back() const noexcept
Accesses the last element.
Definition darray_soa_impl.h:729
GAIA_NODISCARD constexpr bool operator!=(const darr_soa &other) const noexcept
Checks whether two containers differ.
Definition darray_soa_impl.h:822
GAIA_NODISCARD decltype(auto) front() noexcept
Accesses the first element.
Definition darray_soa_impl.h:708
darr_soa(size_type count)
Constructs a container with the requested number of value-initialized elements.
Definition darray_soa_impl.h:292
void push_back(const T &arg)
Appends an element.
Definition darray_soa_impl.h:503
iterator erase(iterator pos) noexcept
Removes the element at pos.
Definition darray_soa_impl.h:586
darr_soa_iterator< T > iterator
Mutable random-access iterator type.
Definition darray_soa_impl.h:242
GAIA_NODISCARD auto crend() const noexcept
Returns the read-only reverse traversal sentinel preceding the first element.
Definition darray_soa_impl.h:802
darr_soa(darr_soa &&other) noexcept
Move-constructs a container.
Definition darray_soa_impl.h:328
GAIA_NODISCARD decltype(auto) back() noexcept
Accesses the last element.
Definition darray_soa_impl.h:722
GAIA_NODISCARD auto rend() noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition darray_soa_impl.h:790
darr_soa & operator=(const darr_soa &other)
Copy-assigns the container.
Definition darray_soa_impl.h:353
void shrink_to_fit()
Reduces allocated storage to match the current size when possible.
Definition darray_soa_impl.h:635
GAIA_NODISCARD size_type max_size() const noexcept
Returns the maximum number of elements supported by this container.
Definition darray_soa_impl.h:702
GAIA_NODISCARD auto rbegin() noexcept
Returns a reverse traversal iterator to the last element.
Definition darray_soa_impl.h:754
GAIA_NODISCARD size_type size() const noexcept
Returns the number of elements.
Definition darray_soa_impl.h:684
darr_soa(std::initializer_list< T > il)
Constructs a container from an initializer list.
Definition darray_soa_impl.h:320
GAIA_NODISCARD auto begin() const noexcept
Returns an iterator to the first element.
Definition darray_soa_impl.h:742
GAIA_NODISCARD auto begin() noexcept
Returns an iterator to the first element.
Definition darray_soa_impl.h:736
GAIA_NODISCARD auto end() noexcept
Returns an iterator one past the last element.
Definition darray_soa_impl.h:772
darr_soa(InputIt first, InputIt last)
Constructs a container from an iterator range.
Definition darray_soa_impl.h:301
iterator insert(iterator pos, const T &arg)
Insert the element to the position given by iterator pos.
Definition darray_soa_impl.h:543
void pop_back() noexcept
Removes the last element.
Definition darray_soa_impl.h:531
darr_soa & operator=(std::initializer_list< T > il)
Replaces the elements from an initializer list.
Definition darray_soa_impl.h:345
GAIA_NODISCARD pointer data() noexcept
Returns a pointer to the element storage.
Definition darray_soa_impl.h:393
Array with variable size of elements of type.
Definition darray_impl.h:27
darr_detail::size_type size_type
Unsigned type used for sizes and indices.
Definition darray_impl.h:44
GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept
Accesses an element without bounds checking in optimized builds.
Definition darray_impl.h:206
core::random_access_iterator_tag iterator_category
Iterator category exposed by the container.
Definition darray_impl.h:51
GAIA_NODISCARD auto begin() noexcept
Returns an iterator to the first element.
Definition darray_impl.h:556
GAIA_NODISCARD bool operator==(const darr &other) const noexcept
Compares two containers element by element.
Definition darray_impl.h:629
T value_type
Element type stored by the container.
Definition darray_impl.h:30
pointer iterator
Mutable random-access iterator type.
Definition darray_impl.h:47
darr_detail::difference_type difference_type
Type used for iterator differences.
Definition darray_impl.h:42
GAIA_NODISCARD constexpr bool operator!=(const darr &other) const noexcept
Checks whether two containers differ.
Definition darray_impl.h:642
GAIA_NODISCARD auto end() noexcept
Returns an iterator one past the last element.
Definition darray_impl.h:592
View policy for accessing and storing data in the SoA way. Good for SIMD processing.
Definition data_layout_policy.h:402
GAIA_NODISCARD static constexpr ValueType get(std::span< const uint8_t > s, size_t idx) noexcept
Reconstructs a value from its SoA fields.
Definition data_layout_policy.h:530
static void mem_pop_block(void *pData, size_t cap, size_t count, size_t n)
Poisons removed SoA values for the memory sanitizer.
Definition data_layout_policy.h:514
static void mem_add_block(void *pData, size_t cap, size_t count)
Registers a newly allocated SoA range with the memory sanitizer.
Definition data_layout_policy.h:464
uint8_t * TargetCastType
Pointer type used to address SoA storage.
Definition data_layout_policy.h:408
GAIA_NODISCARD static constexpr auto set(std::span< uint8_t > s, size_t idx) noexcept
Returns a mutable proxy for one complete value.
Definition data_layout_policy.h:582
static void mem_push_block(void *pData, size_t cap, size_t count, size_t n)
Makes newly appended SoA values addressable by the memory sanitizer.
Definition data_layout_policy.h:497
Storage policy for a selected layout and item type.
Definition data_layout_policy.h:123