Gaia-ECS v1.0.0
A simple and powerful entity component system
Loading...
Searching...
No Matches
darray_ext_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 {
19 namespace darr_ext_detail {
20 using difference_type = uint32_t;
21 using size_type = uint32_t;
22 } // namespace darr_ext_detail
24
29 template <typename T, darr_ext_detail::size_type N, typename Allocator = mem::DefaultAllocatorAdaptor>
30 class darr_ext {
31 public:
32 static_assert(N > 0);
33
35 using value_type = T;
37 using reference = T&;
39 using const_reference = const T&;
41 using pointer = T*;
43 using const_pointer = const T*;
47 using difference_type = darr_ext_detail::difference_type;
49 using size_type = darr_ext_detail::size_type;
50
57
59 static constexpr size_t value_size = sizeof(T);
61 static constexpr size_type extent = N;
64
65 private:
67 mem::raw_data_holder<T, allocated_bytes> m_data;
69 uint8_t* m_pDataHeap = nullptr;
71 uint8_t* m_pData = m_data;
73 size_type m_cnt = size_type(0);
75 size_type m_cap = extent;
76
77 void try_grow() {
78 const auto cnt = size();
79 const auto cap = capacity();
80
81 // Unless we reached the capacity don't do anything
82 if GAIA_LIKELY (cnt < cap)
83 return;
84
85 // We increase the capacity in multiples of 1.5 which is about the golden ratio (1.618).
86 // This means we prefer more frequent allocations over memory fragmentation.
87 m_cap = (cap * 3 + 1) / 2;
88
89 if GAIA_UNLIKELY (m_pDataHeap == nullptr) {
90 // If no heap memory is allocated yet we need to allocate it and move the old stack elements to it
91 m_pDataHeap = view_policy::template alloc<Allocator>(m_cap);
92 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pDataHeap, m_cap, cnt);
93 mem::move_elements<T, false>(m_pDataHeap, m_data, cnt, 0, m_cap, cap);
94 } else {
95 // Move items from the old heap array to the new one. Delete the old
96 auto* pDataOld = m_pDataHeap;
97 m_pDataHeap = view_policy::template alloc<Allocator>(m_cap);
98 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pDataHeap, m_cap, cnt);
99 mem::move_elements<T, false>(m_pDataHeap, pDataOld, cnt, 0, m_cap, cap);
100 view_policy::template free<Allocator>(pDataOld, cap, cnt);
101 }
102
103 m_pData = m_pDataHeap;
104 }
105
106 public:
107 darr_ext() noexcept = default;
109 darr_ext(core::zero_t) noexcept {}
110
115 resize(count, value);
116 }
117
121 resize(count);
122 }
123
128 template <typename InputIt>
129 darr_ext(InputIt first, InputIt last) {
130 const auto count = (size_type)core::distance(first, last);
131 resize(count);
132
133 if constexpr (std::is_pointer_v<InputIt>) {
134 for (size_type i = 0; i < count; ++i)
135 operator[](i) = first[i];
136 } else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
137 for (size_type i = 0; i < count; ++i)
138 operator[](i) = *(first[i]);
139 } else {
140 size_type i = 0;
141 for (auto it = first; it != last; ++it)
142 operator[](++i) = *it;
143 }
144 }
145
148 darr_ext(std::initializer_list<T> il): darr_ext(il.begin(), il.end()) {}
149
152 darr_ext(const darr_ext& other): darr_ext(other.begin(), other.end()) {}
153
156 darr_ext(darr_ext&& other) noexcept {
157 GAIA_ASSERT(core::addressof(other) != this);
158
159 // Moving from stack-allocated source
160 if (other.m_pDataHeap == nullptr) {
161 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_data, extent, other.size());
162 mem::move_elements<T, false>(m_data, other.m_data, other.size(), 0, extent, other.extent);
163 GAIA_MEM_SANI_DEL_BLOCK(value_size, other.m_data, extent, other.size());
164 m_pDataHeap = nullptr;
165 m_pData = m_data;
166 } else {
167 m_pDataHeap = other.m_pDataHeap;
168 m_pData = m_pDataHeap;
169 }
170
171 m_cnt = other.m_cnt;
172 m_cap = other.m_cap;
173
174 other.m_pDataHeap = nullptr;
175 other.m_pData = other.m_data;
176 other.m_cnt = size_type(0);
177 other.m_cap = extent;
178 }
179
183 darr_ext& operator=(std::initializer_list<T> il) {
184 *this = darr_ext(il.begin(), il.end());
185 return *this;
186 }
187
191 darr_ext& operator=(const darr_ext& other) {
192 GAIA_ASSERT(core::addressof(other) != this);
193
194 resize(other.size());
195 mem::copy_elements<T, false>(
196 m_pData, (const uint8_t*)other.m_pData, other.size(), 0, capacity(), other.capacity());
197
198 return *this;
199 }
200
204 darr_ext& operator=(darr_ext&& other) noexcept {
205 GAIA_ASSERT(core::addressof(other) != this);
206
207 // Release previously allocated memory or its stack-container annotation.
208 if (m_pDataHeap != nullptr)
209 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
210 else
211 GAIA_MEM_SANI_DEL_BLOCK(value_size, m_data, extent, m_cnt);
212
213 // Moving from stack-allocated source
214 if (other.m_pDataHeap == nullptr) {
215 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_data, extent, other.size());
216 mem::move_elements<T, false>(m_data, other.m_data, other.size(), 0, extent, other.extent);
217 GAIA_MEM_SANI_DEL_BLOCK(value_size, other.m_data, extent, other.size());
218 m_pDataHeap = nullptr;
219 m_pData = m_data;
220 } else {
221 m_pDataHeap = other.m_pDataHeap;
222 m_pData = m_pDataHeap;
223 }
224
225 m_cnt = other.m_cnt;
226 m_cap = other.m_cap;
227
228 other.m_pDataHeap = nullptr;
229 other.m_pData = other.m_data;
230 other.m_cnt = size_type(0);
231 other.m_cap = extent;
232
233 return *this;
234 }
235
236 ~darr_ext() {
237 if (m_pDataHeap != nullptr)
238 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
239 else
240 GAIA_MEM_SANI_DEL_BLOCK(value_size, m_data, extent, m_cnt);
241 }
242
243 GAIA_CLANG_WARNING_PUSH()
244 // Memory is aligned so we can silence this warning
245 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
246
249 GAIA_NODISCARD pointer data() noexcept {
250 return reinterpret_cast<pointer>(m_pData);
251 }
252
255 GAIA_NODISCARD const_pointer data() const noexcept {
256 return reinterpret_cast<const_pointer>(m_pData);
257 }
258
262 GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept {
263 GAIA_ASSERT(pos < size());
264 return view_policy::set({(typename view_policy::TargetCastType)m_pData, size()}, pos);
265 }
266
270 GAIA_NODISCARD decltype(auto) operator[](size_type pos) const noexcept {
271 GAIA_ASSERT(pos < size());
272 return view_policy::get({(typename view_policy::TargetCastType)m_pData, size()}, pos);
273 }
274
275 GAIA_CLANG_WARNING_POP()
276
277
280 if (cap <= m_cap)
281 return;
282
283 auto* pDataOld = m_pDataHeap;
284 m_pDataHeap = view_policy::template alloc<Allocator>(cap);
285 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pDataHeap, cap, m_cnt);
286 if (pDataOld != nullptr) {
287 mem::move_elements<T, false>(m_pDataHeap, pDataOld, m_cnt, 0, cap, m_cap);
288 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
289 } else {
290 mem::move_elements<T, false>(m_pDataHeap, m_data, m_cnt, 0, cap, m_cap);
291 GAIA_MEM_SANI_DEL_BLOCK(value_size, m_data, m_cap, m_cnt);
292 }
293
294 m_cap = cap;
295 m_pData = m_pDataHeap;
296 }
297
300 void resize(size_type count) {
301 if (count == m_cnt)
302 return;
303
304 // Resizing to a smaller size
305 if (count < m_cnt) {
306 // Destroy elements at the end
307 core::call_dtor_n(&data()[count], m_cnt - count);
308 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt, m_cnt - count);
309
310 m_cnt = count;
311 return;
312 }
313
314 // Resizing to a bigger size but still within allocated capacity
315 if (count <= m_cap) {
316 // Construct new elements
317 GAIA_MEM_SANI_PUSH_N(value_size, data(), m_cap, m_cnt, count - m_cnt);
318 core::call_ctor_n(&data()[m_cnt], count - m_cnt);
319
320 m_cnt = count;
321 return;
322 }
323
324 auto* pDataOld = m_pDataHeap;
325 m_pDataHeap = view_policy::template alloc<Allocator>(count);
326 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pDataHeap, count, count);
327 auto* pDataNew = reinterpret_cast<pointer>(m_pDataHeap);
328 if (pDataOld != nullptr) {
329 mem::move_elements<T, false>(m_pDataHeap, pDataOld, m_cnt, 0, count, m_cap);
330 core::call_ctor_n(&pDataNew[m_cnt], count - m_cnt);
331 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
332 } else {
333 mem::move_elements<T, false>(m_pDataHeap, m_data, m_cnt, 0, count, m_cap);
334 GAIA_MEM_SANI_DEL_BLOCK(value_size, m_data, m_cap, m_cnt);
335 }
336
337 m_cap = count;
338 m_cnt = count;
339 m_pData = m_pDataHeap;
340 }
341
345 void resize(size_type count, const_reference value) {
346 const auto oldCount = m_cnt;
347 resize(count);
348
349 if constexpr (std::is_copy_constructible_v<value_type>) {
350 const value_type valueCopy = value;
351 for (size_type i = oldCount; i < m_cnt; ++i)
352 operator[](i) = valueCopy;
353 } else {
354 for (size_type i = oldCount; i < m_cnt; ++i)
355 operator[](i) = value;
356 }
357 }
358
361 void push_back(const T& arg) {
362 try_grow();
363
364 GAIA_MEM_SANI_PUSH(value_size, data(), m_cap, m_cnt);
365 auto* ptr = &data()[m_cnt++];
366 core::call_ctor(ptr, arg);
367 }
368
371 void push_back(T&& arg) {
372 try_grow();
373
374 GAIA_MEM_SANI_PUSH(value_size, data(), m_cap, m_cnt);
375 auto* ptr = &data()[m_cnt++];
376 core::call_ctor(ptr, GAIA_MOV(arg));
377 }
378
383 template <typename... Args>
384 decltype(auto) emplace_back(Args&&... args) {
385 try_grow();
386
387 GAIA_MEM_SANI_PUSH(value_size, data(), m_cap, m_cnt);
388 auto* ptr = &data()[m_cnt++];
389 core::call_ctor(ptr, GAIA_FWD(args)...);
390 return (reference)*ptr;
391 }
392
395 GAIA_ASSERT(!empty());
396
397 auto* ptr = &data()[m_cnt - 1];
398 core::call_dtor(ptr);
399 GAIA_MEM_SANI_POP(value_size, data(), m_cap, m_cnt);
400
401 --m_cnt;
402 }
403
409 GAIA_ASSERT(pos >= data());
410 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
411
412 const auto idxSrc = (size_type)core::distance(begin(), pos);
413 try_grow();
414 const auto idxDst = (size_type)core::distance(begin(), end()) + 1;
415
416 GAIA_MEM_SANI_PUSH(value_size, data(), m_cap, m_cnt);
417 mem::shift_elements_right<T, false>(m_pData, idxDst, idxSrc, m_cap);
418 auto* ptr = &data()[idxSrc];
419 core::call_ctor(ptr, arg);
420
421 ++m_cnt;
422
423 return iterator(ptr);
424 }
425
431 GAIA_ASSERT(pos >= data());
432 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
433
434 const auto idxSrc = (size_type)core::distance(begin(), pos);
435 try_grow();
436 const auto idxDst = (size_type)core::distance(begin(), end());
437
438 GAIA_MEM_SANI_PUSH(value_size, data(), m_cap, m_cnt);
439 mem::shift_elements_right<T, false>(m_pData, idxDst, idxSrc, m_cap);
440 auto* ptr = &data()[idxSrc];
441 core::call_ctor(ptr, GAIA_MOV(arg));
442
443 ++m_cnt;
444
445 return iterator(ptr);
446 }
447
452 GAIA_ASSERT(pos >= data());
453 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
454
455 if (empty())
456 return end();
457
458 const auto idxSrc = (size_type)core::distance(begin(), pos);
459 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
460
461 mem::shift_elements_left<T, false>(m_pData, idxDst, idxSrc, m_cap);
462 // Destroy if it's the last element
463 auto* ptr = &data()[m_cnt - 1];
464 core::call_dtor(ptr);
465 GAIA_MEM_SANI_POP(value_size, data(), m_cap, m_cnt);
466
467 --m_cnt;
468
469 return iterator(&data()[idxSrc]);
470 }
471
476 iterator erase(iterator first, iterator last) noexcept {
477 GAIA_ASSERT(first >= data())
478 GAIA_ASSERT(empty() || (first < iterator(data() + size())));
479 GAIA_ASSERT(last > first);
480 GAIA_ASSERT(last <= iterator(data() + size()));
481
482 if (empty())
483 return end();
484
485 const auto idxSrc = (size_type)core::distance(begin(), first);
486 const auto idxDst = size();
487 const auto cnt = (size_type)(last - first);
488
489 mem::shift_elements_left_fast<T, false>(m_pData, idxDst, idxSrc, cnt, m_cap);
490 // Destroy if it's the last element
491 core::call_dtor_n(&data()[m_cnt - cnt], cnt);
492 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt, cnt);
493
494 m_cnt -= cnt;
495
496 return iterator(&data()[idxSrc]);
497 }
498
501 resize(0);
502 }
503
506 const auto cap = capacity();
507 const auto cnt = size();
508
509 if (cap == cnt)
510 return;
511
512 if (m_pDataHeap != nullptr) {
513 auto* pDataOld = m_pDataHeap;
514
515 if (cnt < extent) {
516 mem::move_elements<T, false>(m_data, pDataOld, cnt, 0);
517 m_pData = m_data;
518 m_cap = extent;
519 } else {
520 m_pDataHeap = view_policy::template alloc<Allocator>(m_cap = cnt);
521 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pDataHeap, m_cap, m_cnt);
522 mem::move_elements<T, false>(m_pDataHeap, pDataOld, cnt, 0);
523 m_pData = m_pDataHeap;
524 }
525
526 GAIA_MEM_SANI_DEL_BLOCK(value_size, pDataOld, cap, cnt);
527 view_policy::template free<Allocator>(pDataOld);
528 } else
529 resize(cnt);
530 }
531
536 template <typename Func>
537 auto retain(Func&& func) noexcept {
538 size_type erased = 0;
539 size_type idxDst = 0;
540 size_type idxSrc = 0;
541
542 while (idxSrc < m_cnt) {
543 if (func(operator[](idxSrc))) {
544 if (idxDst < idxSrc) {
545 auto* ptr = (uint8_t*)data();
546 mem::move_element<T, false>(ptr, ptr, idxDst, idxSrc, m_cap, m_cap);
547 auto* ptr2 = &data()[idxSrc];
548 core::call_dtor(ptr2);
549 }
550 ++idxDst;
551 } else {
552 auto* ptr = &data()[idxSrc];
553 core::call_dtor(ptr);
554 ++erased;
555 }
556
557 ++idxSrc;
558 }
559
560 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt, erased);
561
562 m_cnt -= erased;
563 return idxDst;
564 }
565
568 GAIA_NODISCARD size_type size() const noexcept {
569 return m_cnt;
570 }
571
574 GAIA_NODISCARD bool empty() const noexcept {
575 return size() == 0;
576 }
577
580 GAIA_NODISCARD size_type capacity() const noexcept {
581 return m_cap;
582 }
583
586 GAIA_NODISCARD size_type max_size() const noexcept {
587 return N;
588 }
589
592 GAIA_NODISCARD decltype(auto) front() noexcept {
593 GAIA_ASSERT(!empty());
594 return (reference)*begin();
595 }
596
599 GAIA_NODISCARD decltype(auto) front() const noexcept {
600 GAIA_ASSERT(!empty());
601 return (const_reference)*begin();
602 }
603
606 GAIA_NODISCARD decltype(auto) back() noexcept {
607 GAIA_ASSERT(!empty());
608 return (reference) operator[](m_cnt - 1);
609 }
610
613 GAIA_NODISCARD decltype(auto) back() const noexcept {
614 GAIA_ASSERT(!empty());
615 return (const_reference) operator[](m_cnt - 1);
616 }
617
620 GAIA_NODISCARD auto begin() noexcept {
621 return iterator(data());
622 }
623
626 GAIA_NODISCARD auto begin() const noexcept {
627 return const_iterator(data());
628 }
629
632 GAIA_NODISCARD auto cbegin() const noexcept {
633 return const_iterator(data());
634 }
635
638 GAIA_NODISCARD auto rbegin() noexcept {
639 return iterator((pointer)&back());
640 }
641
644 GAIA_NODISCARD auto rbegin() const noexcept {
646 }
647
650 GAIA_NODISCARD auto crbegin() const noexcept {
652 }
653
656 GAIA_NODISCARD auto end() noexcept {
657 return iterator(data() + size());
658 }
659
662 GAIA_NODISCARD auto end() const noexcept {
663 return const_iterator(data() + size());
664 }
665
668 GAIA_NODISCARD auto cend() const noexcept {
669 return const_iterator(data() + size());
670 }
671
674 GAIA_NODISCARD auto rend() noexcept {
675 return iterator(data() - 1);
676 }
677
680 GAIA_NODISCARD auto rend() const noexcept {
681 return const_iterator(data() - 1);
682 }
683
686 GAIA_NODISCARD auto crend() const noexcept {
687 return const_iterator(data() - 1);
688 }
689
693 GAIA_NODISCARD bool operator==(const darr_ext& other) const noexcept {
694 if (m_cnt != other.m_cnt)
695 return false;
696 const size_type n = size();
697 for (size_type i = 0; i < n; ++i)
698 if (!(operator[](i) == other[i]))
699 return false;
700 return true;
701 }
702
706 GAIA_NODISCARD constexpr bool operator!=(const darr_ext& other) const noexcept {
707 return !operator==(other);
708 }
709 };
710
712 namespace detail {
713 template <typename T, uint32_t N, uint32_t... I>
714 darr_ext<std::remove_cv_t<T>, N> to_sarray_impl(T (&a)[N], std::index_sequence<I...> /*no_name*/) {
715 return {{a[I]...}};
716 }
717 } // namespace detail
719
725 template <typename T, uint32_t N>
726 darr_ext<std::remove_cv_t<T>, N> to_sarray(T (&a)[N]) {
727 return detail::to_sarray_impl(a, std::make_index_sequence<N>{});
728 }
729
730 } // namespace cnt
731
732} // namespace gaia
Array of elements of type.
Definition darray_ext_impl.h:30
void pop_back() noexcept
Removes the last element.
Definition darray_ext_impl.h:394
GAIA_NODISCARD auto end() const noexcept
Returns an iterator one past the last element.
Definition darray_ext_impl.h:662
void resize(size_type count, const_reference value)
Changes the size and initializes new elements from a value.
Definition darray_ext_impl.h:345
GAIA_NODISCARD size_type size() const noexcept
Returns the number of elements.
Definition darray_ext_impl.h:568
GAIA_NODISCARD decltype(auto) front() const noexcept
Accesses the first element.
Definition darray_ext_impl.h:599
darr_ext(darr_ext &&other) noexcept
Move-constructs a container.
Definition darray_ext_impl.h:156
darr_ext & operator=(darr_ext &&other) noexcept
Move-assigns the container.
Definition darray_ext_impl.h:204
darr_ext(size_type count)
Constructs a container with the requested number of value-initialized elements.
Definition darray_ext_impl.h:120
darr_ext & operator=(std::initializer_list< T > il)
Replaces the elements from an initializer list.
Definition darray_ext_impl.h:183
GAIA_NODISCARD size_type max_size() const noexcept
Returns the maximum number of elements supported by this container.
Definition darray_ext_impl.h:586
iterator insert(iterator pos, T &&arg)
Insert the element to the position given by iterator pos.
Definition darray_ext_impl.h:430
void shrink_to_fit()
Reduces allocated storage to match the current size when possible.
Definition darray_ext_impl.h:505
GAIA_NODISCARD auto rbegin() noexcept
Returns a reverse traversal iterator to the last element.
Definition darray_ext_impl.h:638
GAIA_NODISCARD auto rend() noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition darray_ext_impl.h:674
GAIA_NODISCARD auto crbegin() const noexcept
Returns a read-only reverse traversal iterator to the last element.
Definition darray_ext_impl.h:650
const_pointer const_iterator
Read-only random-access iterator type.
Definition darray_ext_impl.h:54
pointer iterator
Mutable random-access iterator type.
Definition darray_ext_impl.h:52
iterator insert(iterator pos, const T &arg)
Insert the element to the position given by iterator pos.
Definition darray_ext_impl.h:408
GAIA_NODISCARD auto rend() const noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition darray_ext_impl.h:680
darr_ext(size_type count, const_reference value)
Constructs a container with copies of a value.
Definition darray_ext_impl.h:114
GAIA_NODISCARD auto cbegin() const noexcept
Returns a read-only iterator to the first element.
Definition darray_ext_impl.h:632
GAIA_NODISCARD decltype(auto) front() noexcept
Accesses the first element.
Definition darray_ext_impl.h:592
void reserve(size_type cap)
Ensures storage for at least the requested number of elements.
Definition darray_ext_impl.h:279
GAIA_NODISCARD auto begin() noexcept
Returns an iterator to the first element.
Definition darray_ext_impl.h:620
iterator erase(iterator first, iterator last) noexcept
Removes the elements in the range [first, last)
Definition darray_ext_impl.h:476
darr_ext(InputIt first, InputIt last)
Constructs a container from an iterator range.
Definition darray_ext_impl.h:129
GAIA_NODISCARD auto rbegin() const noexcept
Returns a reverse traversal iterator to the last element.
Definition darray_ext_impl.h:644
void push_back(const T &arg)
Appends an element.
Definition darray_ext_impl.h:361
GAIA_NODISCARD auto end() noexcept
Returns an iterator one past the last element.
Definition darray_ext_impl.h:656
GAIA_NODISCARD constexpr bool operator!=(const darr_ext &other) const noexcept
Checks whether two containers differ.
Definition darray_ext_impl.h:706
darr_ext_detail::size_type size_type
Unsigned type used for sizes and indices.
Definition darray_ext_impl.h:49
static constexpr size_t value_size
Size of one element in bytes.
Definition darray_ext_impl.h:59
darr_ext(std::initializer_list< T > il)
Constructs a container from an initializer list.
Definition darray_ext_impl.h:148
GAIA_NODISCARD auto cend() const noexcept
Returns a read-only iterator one past the last element.
Definition darray_ext_impl.h:668
GAIA_NODISCARD auto crend() const noexcept
Returns the read-only reverse traversal sentinel preceding the first element.
Definition darray_ext_impl.h:686
auto retain(Func &&func) noexcept
Removes all elements that fail the predicate.
Definition darray_ext_impl.h:537
T * pointer
Mutable element pointer type.
Definition darray_ext_impl.h:41
darr_ext(const darr_ext &other)
Copy-constructs a container.
Definition darray_ext_impl.h:152
void clear() noexcept
Removes all elements.
Definition darray_ext_impl.h:500
static constexpr size_type extent
Fixed capacity of the container.
Definition darray_ext_impl.h:61
darr_ext & operator=(const darr_ext &other)
Copy-assigns the container.
Definition darray_ext_impl.h:191
darr_ext_detail::difference_type difference_type
Type used for iterator differences.
Definition darray_ext_impl.h:47
GAIA_NODISCARD decltype(auto) back() noexcept
Accesses the last element.
Definition darray_ext_impl.h:606
GAIA_NODISCARD const_pointer data() const noexcept
Returns a pointer to the element storage.
Definition darray_ext_impl.h:255
GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept
Accesses an element without bounds checking in optimized builds.
Definition darray_ext_impl.h:262
iterator erase(iterator pos) noexcept
Removes the element at pos.
Definition darray_ext_impl.h:451
decltype(auto) emplace_back(Args &&... args)
Constructs and appends an element.
Definition darray_ext_impl.h:384
GAIA_NODISCARD auto begin() const noexcept
Returns an iterator to the first element.
Definition darray_ext_impl.h:626
GAIA_NODISCARD decltype(auto) back() const noexcept
Accesses the last element.
Definition darray_ext_impl.h:613
const T * const_pointer
Read-only element pointer type.
Definition darray_ext_impl.h:43
void push_back(T &&arg)
Appends an element.
Definition darray_ext_impl.h:371
GAIA_NODISCARD bool operator==(const darr_ext &other) const noexcept
Compares two containers element by element.
Definition darray_ext_impl.h:693
GAIA_NODISCARD pointer data() noexcept
Returns a pointer to the element storage.
Definition darray_ext_impl.h:249
static constexpr uint32_t allocated_bytes
Number of bytes reserved by the inline storage.
Definition darray_ext_impl.h:63
void resize(size_type count)
Changes the number of elements.
Definition darray_ext_impl.h:300
GAIA_NODISCARD bool empty() const noexcept
Checks whether the container has no elements.
Definition darray_ext_impl.h:574
GAIA_NODISCARD size_type capacity() const noexcept
Returns the number of elements that fit without reallocation.
Definition darray_ext_impl.h:580
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 size_type size() const noexcept
Returns the number of elements.
Definition darray_impl.h:504
GAIA_NODISCARD auto begin() noexcept
Returns an iterator to the first element.
Definition darray_impl.h:556
darr_detail::difference_type difference_type
Type used for iterator differences.
Definition darray_impl.h:42
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 AoS way. Good for random access and when accessing ...
Definition data_layout_policy.h:162
static GAIA_NODISCARD constexpr uint32_t get_min_byte_size(uintptr_t addr, size_t cnt) noexcept
Calculates the bytes required for a value range.
Definition data_layout_policy.h:175
std::add_pointer_t< ValueType > TargetCastType
Pointer type used to address stored values.
Definition data_layout_policy.h:164
GAIA_NODISCARD static constexpr ValueType & set(std::span< ValueType > s, size_t idx) noexcept
Returns a mutable value reference from an AoS span.
Definition data_layout_policy.h:238
GAIA_NODISCARD static constexpr const ValueType & get(std::span< const ValueType > s, size_t idx) noexcept
Returns a read-only value reference from an AoS span.
Definition data_layout_policy.h:230