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 T& value) {
282 resize(count);
283 for (auto it: *this)
284 *it = value;
285 }
286
287 darr_ext_soa(size_type count) {
288 resize(count);
289 }
290
291 template <typename InputIt>
292 darr_ext_soa(InputIt first, InputIt last) {
293 const auto count = (size_type)core::distance(first, last);
294 resize(count);
295
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]);
302 } else {
303 size_type i = 0;
304 for (auto it = first; it != last; ++it)
305 operator[](++i) = *it;
306 }
307 }
308
309 darr_ext_soa(std::initializer_list<T> il): darr_ext_soa(il.begin(), il.end()) {}
310
311 darr_ext_soa(const darr_ext_soa& other): darr_ext_soa(other.begin(), other.end()) {}
312
313 darr_ext_soa(darr_ext_soa&& other) noexcept {
314 GAIA_ASSERT(core::addressof(other) != this);
315
316 // Moving from stack-allocated source
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;
322 m_pData = m_data;
323 } else {
324 m_pDataHeap = other.m_pDataHeap;
325 m_pData = m_pDataHeap;
326 }
327
328 m_cnt = other.m_cnt;
329 m_cap = other.m_cap;
330
331 other.m_pDataHeap = nullptr;
332 other.m_pData = other.m_data;
333 other.m_cnt = size_type(0);
334 other.m_cap = extent;
335 }
336
337 darr_ext_soa& operator=(std::initializer_list<T> il) {
338 *this = darr_ext_soa(il.begin(), il.end());
339 return *this;
340 }
341
342 darr_ext_soa& operator=(const darr_ext_soa& other) {
343 GAIA_ASSERT(core::addressof(other) != this);
344
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());
348
349 return *this;
350 }
351
352 darr_ext_soa& operator=(darr_ext_soa&& other) noexcept {
353 GAIA_ASSERT(core::addressof(other) != this);
354
355 // Release previously allocated memory if there was anything
356 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
357
358 // Moving from stack-allocated source
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;
364 m_pData = m_data;
365 } else {
366 m_pDataHeap = other.m_pDataHeap;
367 m_pData = m_pDataHeap;
368 }
369
370 m_cnt = other.m_cnt;
371 m_cap = other.m_cap;
372
373 other.m_cnt = size_type(0);
374 other.m_cap = extent;
375 other.m_pDataHeap = nullptr;
376 other.m_pData = other.m_data;
377
378 return *this;
379 }
380
381 ~darr_ext_soa() {
382 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
383 }
384
385 GAIA_CLANG_WARNING_PUSH()
386 // Memory is aligned so we can silence this warning
387 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
388
389 GAIA_NODISCARD pointer data() noexcept {
390 return reinterpret_cast<pointer>(m_pData);
391 }
392
393 GAIA_NODISCARD const_pointer data() const noexcept {
394 return reinterpret_cast<const_pointer>(m_pData);
395 }
396
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);
400 }
401
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);
405 }
406
407 GAIA_CLANG_WARNING_POP()
408
409 void reserve(size_type cap) {
410 if (cap <= m_cap)
411 return;
412
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);
416 if (m_pDataHeap) {
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);
419 } else {
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);
422 }
423
424 m_cap = cap;
425 m_pData = m_pDataHeap;
426 }
427
428 void resize(size_type count) {
429 if (count == m_cnt)
430 return;
431
432 // Resizing to a smaller size
433 if (count < m_cnt) {
434 view_policy::mem_pop_block(data(), m_cap, m_cnt, m_cnt - count);
435
436 m_cnt = count;
437 return;
438 }
439
440 // Resizing to a bigger size but still within allocated capacity
441 if (count <= m_cap) {
442 view_policy::mem_push_block(data(), m_cap, m_cnt, count - m_cnt);
443
444 m_cnt = count;
445 return;
446 }
447
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);
454 } else {
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);
457 }
458
459 m_cap = count;
460 m_cnt = count;
461 m_pData = m_pDataHeap;
462 }
463
464 void push_back(const T& arg) {
465 try_grow();
466
467 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
468 operator[](m_cnt++) = arg;
469 }
470
471 void push_back(T&& arg) {
472 try_grow();
473
474 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
475 operator[](m_cnt++) = GAIA_MOV(arg);
476 }
477
478 template <typename... Args>
479 decltype(auto) emplace_back(Args&&... args) {
480 try_grow();
481
482 view_policy::mem_push_block(data(), m_cap, m_cnt, 1);
483 operator[](m_cnt++) = T(GAIA_FWD(args)...);
484 }
485
486 void pop_back() noexcept {
487 GAIA_ASSERT(!empty());
488
489 view_policy::mem_pop_block(data(), m_cap, m_cnt, 1);
490
491 --m_cnt;
492 }
493
497 iterator insert(iterator pos, const T& arg) {
498 GAIA_ASSERT(pos >= data());
499 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
500
501 const auto idxSrc = (size_type)core::distance(begin(), pos);
502 try_grow();
503 const auto idxDst = (size_type)core::distance(begin(), end()) + 1;
504
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);
507
508 operator[](idxSrc) = arg;
509
510 ++m_cnt;
511
512 return iterator(m_pData, capacity(), idxSrc);
513 }
514
518 iterator insert(iterator pos, T&& arg) {
519 GAIA_ASSERT(pos >= data());
520 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
521
522 const auto idxSrc = (size_type)core::distance(begin(), pos);
523 try_grow();
524 const auto idxDst = (size_type)core::distance(begin(), end());
525
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);
528
529 operator[](idxSrc) = GAIA_MOV(arg);
530
531 ++m_cnt;
532
533 return iterator(m_pData, capacity(), idxSrc);
534 }
535
538 iterator erase(iterator pos) noexcept {
539 GAIA_ASSERT(pos >= data());
540 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
541
542 if (empty())
543 return end();
544
545 const auto idxSrc = (size_type)core::distance(begin(), pos);
546 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
547
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);
550
551 --m_cnt;
552
553 return iterator(m_pData, capacity(), idxSrc);
554 }
555
559 iterator erase(iterator first, iterator last) noexcept {
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()));
564
565 if (empty())
566 return end();
567
568 const auto idxSrc = (size_type)core::distance(begin(), first);
569 const auto idxDst = size();
570 const auto cnt = (size_type)(last - first);
571
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);
574
575 m_cnt -= cnt;
576
577 return iterator(m_pData, capacity(), idxSrc);
578 }
579
580 void clear() noexcept {
581 resize(0);
582 }
583
584 void shrink_to_fit() {
585 const auto cap = capacity();
586 const auto cnt = size();
587
588 if (cap == cnt)
589 return;
590
591 if (m_pDataHeap != nullptr) {
592 auto* pDataOld = m_pDataHeap;
593
594 if (cnt < extent) {
595 mem::move_elements<T, true>(m_data, pDataOld, cnt, 0);
596 m_pData = m_data;
597 m_cap = extent;
598 } else {
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;
603 }
604
605 view_policy::mem_del_block(pDataOld, cap, cnt);
606 view_policy::template free<Allocator>(pDataOld);
607 } else
608 resize(cnt);
609 }
610
614 template <typename Func>
615 auto retain(Func&& func) noexcept {
616 size_type erased = 0;
617 size_type idxDst = 0;
618 size_type idxSrc = 0;
619
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);
625 }
626 ++idxDst;
627 } else {
628 ++erased;
629 }
630
631 ++idxSrc;
632 }
633
634 view_policy::mem_pop_block(data(), m_cap, m_cnt, erased);
635
636 m_cnt -= erased;
637 return idxDst;
638 }
639
640 GAIA_NODISCARD size_type size() const noexcept {
641 return m_cnt;
642 }
643
644 GAIA_NODISCARD bool empty() const noexcept {
645 return size() == 0;
646 }
647
648 GAIA_NODISCARD size_type capacity() const noexcept {
649 return m_cap;
650 }
651
652 GAIA_NODISCARD size_type max_size() const noexcept {
653 return N;
654 }
655
656 GAIA_NODISCARD decltype(auto) front() noexcept {
657 GAIA_ASSERT(!empty());
658 return *begin();
659 }
660
661 GAIA_NODISCARD decltype(auto) front() const noexcept {
662 GAIA_ASSERT(!empty());
663 return *begin();
664 }
665
666 GAIA_NODISCARD decltype(auto) back() noexcept {
667 GAIA_ASSERT(!empty());
668 return operator[](m_cnt - 1);
669 }
670
671 GAIA_NODISCARD decltype(auto) back() const noexcept {
672 GAIA_ASSERT(!empty());
673 return operator[](m_cnt - 1);
674 }
675
676 GAIA_NODISCARD auto begin() noexcept {
677 return iterator(m_pData, capacity(), 0);
678 }
679
680 GAIA_NODISCARD auto begin() const noexcept {
681 return const_iterator(m_pData, capacity(), 0);
682 }
683
684 GAIA_NODISCARD auto cbegin() const noexcept {
685 return const_iterator(m_pData, capacity(), 0);
686 }
687
688 GAIA_NODISCARD auto rbegin() noexcept {
689 return iterator(m_pData, capacity(), size() - 1);
690 }
691
692 GAIA_NODISCARD auto rbegin() const noexcept {
693 return const_iterator(m_pData, capacity(), size() - 1);
694 }
695
696 GAIA_NODISCARD auto crbegin() const noexcept {
697 return const_iterator(m_pData, capacity(), size() - 1);
698 }
699
700 GAIA_NODISCARD auto end() noexcept {
701 return iterator(m_pData, capacity(), size());
702 }
703
704 GAIA_NODISCARD auto end() const noexcept {
705 return const_iterator(m_pData, capacity(), size());
706 }
707
708 GAIA_NODISCARD auto cend() const noexcept {
709 return const_iterator(m_pData, capacity(), size());
710 }
711
712 GAIA_NODISCARD auto rend() noexcept {
713 return iterator(m_pData, capacity(), -1);
714 }
715
716 GAIA_NODISCARD auto rend() const noexcept {
717 return const_iterator(m_pData, capacity(), -1);
718 }
719
720 GAIA_NODISCARD auto crend() const noexcept {
721 return const_iterator(m_pData, capacity(), -1);
722 }
723
724 GAIA_NODISCARD bool operator==(const darr_ext_soa& other) const noexcept {
725 if (m_cnt != other.m_cnt)
726 return false;
727 const size_type n = size();
728 for (size_type i = 0; i < n; ++i)
729 if (!(operator[](i) == other[i]))
730 return false;
731 return true;
732 }
733
734 GAIA_NODISCARD constexpr bool operator!=(const darr_ext_soa& other) const noexcept {
735 return !operator==(other);
736 }
737
738 template <size_t Item>
739 auto view_mut() noexcept {
740 return mem::data_view_policy<T::gaia_Data_Layout, T>::template set<Item>(
741 std::span<uint8_t>{GAIA_ACC((uint8_t*)m_pData), capacity()});
742 }
743
744 template <size_t Item>
745 auto view() const noexcept {
746 return mem::data_view_policy<T::gaia_Data_Layout, T>::template get<Item>(
747 std::span<const uint8_t>{GAIA_ACC((const uint8_t*)m_pData), capacity()});
748 }
749 };
750
751 namespace detail {
752 template <typename T, uint32_t N, uint32_t... I>
753 darr_ext_soa<std::remove_cv_t<T>, N> to_sarray_impl(T (&a)[N], std::index_sequence<I...> /*no_name*/) {
754 return {{a[I]...}};
755 }
756 } // namespace detail
757
758 template <typename T, uint32_t N>
759 darr_ext_soa<std::remove_cv_t<T>, N> to_sarray(T (&a)[N]) {
760 return detail::to_sarray_impl(a, std::make_index_sequence<N>{});
761 }
762
763 } // namespace cnt
764
765} // 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:615
iterator insert(iterator pos, T &&arg)
Insert the element to the position given by iterator pos.
Definition darray_ext_soa_impl.h:518
iterator erase(iterator first, iterator last) noexcept
Removes the elements in the range [first, last)
Definition darray_ext_soa_impl.h:559
iterator insert(iterator pos, const T &arg)
Insert the element to the position given by iterator pos.
Definition darray_ext_soa_impl.h:497
iterator erase(iterator pos) noexcept
Removes the element at pos.
Definition darray_ext_soa_impl.h:538
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