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/cnt/impl/array_utils.h"
10#include "gaia/core/iterator.h"
11#include "gaia/core/utility.h"
12#include "gaia/mem/data_layout_policy.h"
13#include "gaia/mem/mem_sani.h"
14#include "gaia/mem/mem_utils.h"
15#include "gaia/mem/raw_data_holder.h"
16
17namespace gaia {
18 namespace cnt {
20 namespace darr_ext_detail {
21 using difference_type = int32_t;
22 using size_type = uint32_t;
23 } // namespace darr_ext_detail
25
30 template <typename T, darr_ext_detail::size_type N, typename Allocator = mem::DefaultAllocatorAdaptor>
31 class darr_ext {
32 public:
33 static_assert(N > 0);
34
36 using value_type = T;
38 using reference = T&;
40 using const_reference = const T&;
42 using pointer = T*;
44 using const_pointer = const T*;
48 using difference_type = darr_ext_detail::difference_type;
50 using size_type = darr_ext_detail::size_type;
51
62
64 static constexpr size_t value_size = sizeof(T);
66 static constexpr size_type extent = N;
69
70 private:
72 mem::raw_data_holder<T, allocated_bytes> m_data;
74 uint8_t* m_pDataHeap = nullptr;
76 uint8_t* m_pData = m_data;
78 size_type m_cnt = size_type(0);
80 size_type m_cap = extent;
81
82 void try_grow() {
83 if (m_cnt == m_cap)
84 reserve(m_cap != 0 ? (m_cap * 3 + 1) / 2 : 4);
85 }
86
87 public:
90 darr_ext(core::zero_t) noexcept {}
91
96 resize(count, value);
97 }
98
102 resize(count);
103 }
104
109 template <typename InputIt>
110 darr_ext(InputIt first, InputIt last) {
111 const auto count = (size_type)core::distance(first, last);
112 resize(count);
113
114 if constexpr (std::is_pointer_v<InputIt>) {
115 for (size_type i = 0; i < count; ++i)
116 operator[](i) = first[i];
117 } else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
118 for (size_type i = 0; i < count; ++i)
119 operator[](i) = *(first[i]);
120 } else {
121 size_type i = 0;
122 for (auto it = first; it != last; ++it)
123 operator[](i++) = *it;
124 }
125 }
126
129 darr_ext(std::initializer_list<T> il): darr_ext(il.begin(), il.end()) {}
130
134
137 darr_ext(darr_ext&& other) noexcept {
138 GAIA_ASSERT(core::addressof(other) != this);
139
140 // Moving from stack-allocated source
141 if (other.m_pDataHeap == nullptr) {
142 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_data, extent, other.size());
143 mem::move_ctor_elements<T>(m_data, other.m_data, other.size());
144 core::call_dtor_n(other.data(), other.size());
145 GAIA_MEM_SANI_DEL_BLOCK(value_size, other.m_data, extent, other.size());
146 m_pDataHeap = nullptr;
147 m_pData = m_data;
148 } else {
149 m_pDataHeap = other.m_pDataHeap;
150 m_pData = m_pDataHeap;
151 }
152
153 m_cnt = other.m_cnt;
154 m_cap = other.m_cap;
155
156 other.m_pDataHeap = nullptr;
157 other.m_pData = other.m_data;
158 other.m_cnt = size_type(0);
159 other.m_cap = extent;
160 }
161
165 darr_ext& operator=(std::initializer_list<T> il) {
166 *this = darr_ext(il.begin(), il.end());
167 return *this;
168 }
169
174 GAIA_ASSERT(core::addressof(other) != this);
175
176 resize(other.size());
177 mem::copy_elements<T, false>(
178 m_pData, (const uint8_t*)other.m_pData, other.size(), 0, capacity(), other.capacity());
179
180 return *this;
181 }
182
187 GAIA_ASSERT(core::addressof(other) != this);
188
189 // Release previously allocated memory or its stack-container annotation.
190 if (m_pDataHeap != nullptr)
191 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
192 else {
193 core::call_dtor_n(data(), m_cnt);
194 GAIA_MEM_SANI_DEL_BLOCK(value_size, m_data, extent, m_cnt);
195 }
196
197 // Moving from stack-allocated source
198 if (other.m_pDataHeap == nullptr) {
199 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_data, extent, other.size());
200 mem::move_ctor_elements<T>(m_data, other.m_data, other.size());
201 core::call_dtor_n(other.data(), other.size());
202 GAIA_MEM_SANI_DEL_BLOCK(value_size, other.m_data, extent, other.size());
203 m_pDataHeap = nullptr;
204 m_pData = m_data;
205 } else {
206 m_pDataHeap = other.m_pDataHeap;
207 m_pData = m_pDataHeap;
208 }
209
210 m_cnt = other.m_cnt;
211 m_cap = other.m_cap;
212
213 other.m_pDataHeap = nullptr;
214 other.m_pData = other.m_data;
215 other.m_cnt = size_type(0);
216 other.m_cap = extent;
217
218 return *this;
219 }
220
221 ~darr_ext() {
222 if (m_pDataHeap != nullptr)
223 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
224 else {
225 core::call_dtor_n(data(), m_cnt);
226 GAIA_MEM_SANI_DEL_BLOCK(value_size, m_data, extent, m_cnt);
227 }
228 }
229
230 GAIA_CLANG_WARNING_PUSH()
231 // Memory is aligned so we can silence this warning
232 GAIA_CLANG_WARNING_DISABLE("-Wcast-align")
233
236 GAIA_NODISCARD pointer data() noexcept {
237 return reinterpret_cast<pointer>(m_pData);
238 }
239
242 GAIA_NODISCARD const_pointer data() const noexcept {
243 return reinterpret_cast<const_pointer>(m_pData);
244 }
245
249 GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept {
250 GAIA_ASSERT(pos < size());
251 return view_policy::set({(typename view_policy::TargetCastType)m_pData, size()}, pos);
252 }
253
257 GAIA_NODISCARD decltype(auto) operator[](size_type pos) const noexcept {
258 GAIA_ASSERT(pos < size());
259 return view_policy::get({(typename view_policy::TargetCastType)m_pData, size()}, pos);
260 }
261
262 GAIA_CLANG_WARNING_POP()
263
264
267 if (cap <= m_cap)
268 return;
269
270 auto* pDataOld = m_pDataHeap;
271 m_pDataHeap = view_policy::template alloc<Allocator>(cap);
272 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pDataHeap, cap, m_cnt);
273 if (pDataOld != nullptr) {
274 mem::move_ctor_elements<T>(m_pDataHeap, pDataOld, m_cnt);
275 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
276 } else {
277 mem::move_ctor_elements<T>(m_pDataHeap, m_data, m_cnt);
278 core::call_dtor_n(data(), m_cnt);
279 GAIA_MEM_SANI_DEL_BLOCK(value_size, m_data, m_cap, m_cnt);
280 }
281
282 m_cap = cap;
283 m_pData = m_pDataHeap;
284 }
285
289 void resize(size_type count, ResizePolicy policy = ResizePolicy::Exact) {
290 if (count == m_cnt)
291 return;
292
293 // Resizing to a smaller size
294 if (count < m_cnt) {
295 // Destroy elements at the end
296 core::call_dtor_n(&data()[count], m_cnt - count);
297 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt, m_cnt - count);
298
299 m_cnt = count;
300 return;
301 }
302
303 // Resizing to a bigger size but still within allocated capacity
304 if (count <= m_cap) {
305 // Construct new elements
306 GAIA_MEM_SANI_PUSH_N(value_size, data(), m_cap, m_cnt, count - m_cnt);
307 core::call_ctor_n(&data()[m_cnt], count - m_cnt);
308
309 m_cnt = count;
310 return;
311 }
312
313 const auto cap = detail::resize_capacity(policy, m_cap, count);
314 auto* pDataOld = m_pDataHeap;
315 m_pDataHeap = view_policy::template alloc<Allocator>(cap);
316 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pDataHeap, cap, count);
317 auto* pDataNew = reinterpret_cast<pointer>(m_pDataHeap);
318 if (pDataOld != nullptr) {
319 mem::move_ctor_elements<T>(m_pDataHeap, pDataOld, m_cnt);
320 view_policy::template free<Allocator>(pDataOld, m_cap, m_cnt);
321 } else {
322 mem::move_ctor_elements<T>(m_pDataHeap, m_data, m_cnt);
323 core::call_dtor_n(data(), m_cnt);
324 GAIA_MEM_SANI_DEL_BLOCK(value_size, m_data, m_cap, m_cnt);
325 }
326
327 core::call_ctor_n(&pDataNew[m_cnt], count - m_cnt);
328
329 m_cap = cap;
330 m_cnt = count;
331 m_pData = m_pDataHeap;
332 }
333
338 void resize(size_type count, const_reference value, ResizePolicy policy = ResizePolicy::Exact) {
339 if (count <= m_cnt) {
340 resize(count, policy);
341 return;
342 }
343 const auto oldCount = m_cnt;
344 if constexpr (std::is_copy_constructible_v<value_type>) {
345 const value_type valueCopy = value;
346 resize(count, policy);
347 for (size_type i = oldCount; i < m_cnt; ++i)
348 operator[](i) = valueCopy;
349 } else {
351 valueCopy = value;
352 resize(count, policy);
353 for (size_type i = oldCount; i < m_cnt; ++i)
354 operator[](i) = valueCopy;
355 }
356 }
357
360 void push_back(const T& arg) {
362 }
363
366 void push_back(T&& arg) {
367 emplace_back(GAIA_MOV(arg));
368 }
369
374 template <typename... Args>
375 decltype(auto) emplace_back(Args&&... args) {
376 if GAIA_UNLIKELY (m_cnt == m_cap) {
377 const auto cap = m_cap != 0 ? (m_cap * 3 + 1) / 2 : 4;
378 auto* pDataNew = view_policy::template alloc<Allocator>(cap);
379 GAIA_MEM_SANI_ADD_BLOCK(value_size, pDataNew, cap, m_cnt + 1);
381 core::call_ctor(&static_cast<T*>(static_cast<void*>(pDataNew))[m_cnt], GAIA_FWD(args)...);
382 mem::move_ctor_elements<T>(pDataNew, m_pData, m_cnt);
383 if (m_pDataHeap != nullptr)
384 view_policy::template free<Allocator>(m_pDataHeap, m_cap, m_cnt);
385 else {
386 core::call_dtor_n(data(), m_cnt);
387 GAIA_MEM_SANI_DEL_BLOCK(value_size, m_data, m_cap, m_cnt);
388 }
389 m_pDataHeap = pDataNew;
390 m_pData = pDataNew;
391 m_cap = cap;
392 } else {
393 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
394 core::call_ctor(&data()[m_cnt], GAIA_FWD(args)...);
395 }
396 return (reference)data()[m_cnt++];
397 }
398
401 GAIA_ASSERT(!empty());
402
403 auto* ptr = &data()[m_cnt - 1];
404 core::call_dtor(ptr);
405 GAIA_MEM_SANI_POP(value_size, data(), m_cap, m_cnt);
406
407 --m_cnt;
408 }
409
415 GAIA_ASSERT(pos >= data());
416 GAIA_ASSERT(pos <= iterator(data() + size()));
417
418 T value(arg);
419 const auto idxSrc = (size_type)core::distance(begin(), pos);
420 try_grow();
421 const auto idxDst = (size_type)core::distance(begin(), end());
422
423 GAIA_MEM_SANI_PUSH(value_size, data(), m_cap, m_cnt);
424 auto* ptr = &data()[idxSrc];
425 if (idxSrc == idxDst) {
426 core::call_ctor(ptr, std::move_if_noexcept(value));
427 } else {
428 mem::move_ctor_elements<T>((uint8_t*)&data()[idxDst], (uint8_t*)&data()[idxDst - 1], 1);
429 mem::shift_elements_right<T, false>(m_pData, idxDst - 1, idxSrc, m_cap);
430 mem::move_element<T, false>((uint8_t*)ptr, (uint8_t*)&value, 0, 0, 1, 1);
431 }
432
433 ++m_cnt;
434
435 return iterator(ptr);
436 }
437
443 GAIA_ASSERT(pos >= data());
444 GAIA_ASSERT(pos <= iterator(data() + size()));
445
446 T value(GAIA_MOV(arg));
447 const auto idxSrc = (size_type)core::distance(begin(), pos);
448 try_grow();
449 const auto idxDst = (size_type)core::distance(begin(), end());
450
451 GAIA_MEM_SANI_PUSH(value_size, data(), m_cap, m_cnt);
452 auto* ptr = &data()[idxSrc];
453 if (idxSrc == idxDst) {
454 core::call_ctor(ptr, std::move_if_noexcept(value));
455 } else {
456 mem::move_ctor_elements<T>((uint8_t*)&data()[idxDst], (uint8_t*)&data()[idxDst - 1], 1);
457 mem::shift_elements_right<T, false>(m_pData, idxDst - 1, idxSrc, m_cap);
458 mem::move_element<T, false>((uint8_t*)ptr, (uint8_t*)&value, 0, 0, 1, 1);
459 }
460
461 ++m_cnt;
462
463 return iterator(ptr);
464 }
465
470 GAIA_ASSERT(pos >= data());
471 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
472
473 if (empty())
474 return end();
475
476 const auto idxSrc = (size_type)core::distance(begin(), pos);
477 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
478
479 mem::shift_elements_left<T, false>(m_pData, idxDst, idxSrc, m_cap);
480 // Destroy if it's the last element
481 auto* ptr = &data()[m_cnt - 1];
482 core::call_dtor(ptr);
483 GAIA_MEM_SANI_POP(value_size, data(), m_cap, m_cnt);
484
485 --m_cnt;
486
487 return iterator(&data()[idxSrc]);
488 }
489
494 iterator erase(iterator first, iterator last) noexcept {
495 GAIA_ASSERT(first >= data())
496 GAIA_ASSERT(empty() || (first < iterator(data() + size())));
497 GAIA_ASSERT(last > first);
498 GAIA_ASSERT(last <= iterator(data() + size()));
499
500 if (empty())
501 return end();
502
503 const auto idxSrc = (size_type)core::distance(begin(), first);
504 const auto idxDst = size();
505 const auto cnt = (size_type)(last - first);
506
507 mem::shift_elements_left_fast<T, false>(m_pData, idxDst, idxSrc, cnt, m_cap);
508 // Destroy if it's the last element
509 core::call_dtor_n(&data()[m_cnt - cnt], cnt);
510 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt, cnt);
511
512 m_cnt -= cnt;
513
514 return iterator(&data()[idxSrc]);
515 }
516
519 resize(0);
520 }
521
524 const auto cap = capacity();
525 const auto cnt = size();
526 if (m_pDataHeap == nullptr || (cnt > extent && cap == cnt))
527 return;
528
529 auto* pDataOld = m_pDataHeap;
530 if (cnt <= extent) {
531 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_data, extent, cnt);
532 mem::move_ctor_elements<T>(m_data, pDataOld, cnt);
533 m_pDataHeap = nullptr;
534 m_pData = m_data;
535 m_cap = extent;
536 } else {
537 m_pDataHeap = view_policy::template alloc<Allocator>(cnt);
538 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pDataHeap, cnt, cnt);
539 mem::move_ctor_elements<T>(m_pDataHeap, pDataOld, cnt);
540 m_pData = m_pDataHeap;
541 m_cap = cnt;
542 }
543 view_policy::template free<Allocator>(pDataOld, cap, cnt);
544 }
545
551 template <typename Func>
552 auto retain(Func&& func) noexcept {
553 const auto oldCount = m_cnt;
554 const auto newSize = detail::retain_array<false>(*this, m_cnt, func);
555 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, oldCount, oldCount - m_cnt);
556 return newSize;
557 }
558
561 GAIA_NODISCARD size_type size() const noexcept {
562 return m_cnt;
563 }
564
567 GAIA_NODISCARD bool empty() const noexcept {
568 return size() == 0;
569 }
570
573 GAIA_NODISCARD size_type capacity() const noexcept {
574 return m_cap;
575 }
576
579 GAIA_NODISCARD size_type max_size() const noexcept {
580 return N;
581 }
582
585 GAIA_NODISCARD decltype(auto) front() noexcept {
586 GAIA_ASSERT(!empty());
587 return (reference)*begin();
588 }
589
592 GAIA_NODISCARD decltype(auto) front() const noexcept {
593 GAIA_ASSERT(!empty());
594 return (const_reference)*begin();
595 }
596
599 GAIA_NODISCARD decltype(auto) back() noexcept {
600 GAIA_ASSERT(!empty());
601 return (reference) operator[](m_cnt - 1);
602 }
603
606 GAIA_NODISCARD decltype(auto) back() const noexcept {
607 GAIA_ASSERT(!empty());
608 return (const_reference) operator[](m_cnt - 1);
609 }
610
613 GAIA_NODISCARD auto begin() noexcept {
614 return iterator(data());
615 }
616
619 GAIA_NODISCARD auto begin() const noexcept {
620 return const_iterator(data());
621 }
622
625 GAIA_NODISCARD auto cbegin() const noexcept {
626 return const_iterator(data());
627 }
628
631 GAIA_NODISCARD auto rbegin() noexcept {
632 return reverse_iterator(end());
633 }
634
637 GAIA_NODISCARD auto rbegin() const noexcept {
638 return const_reverse_iterator(end());
639 }
640
643 GAIA_NODISCARD auto crbegin() const noexcept {
645 }
646
649 GAIA_NODISCARD auto end() noexcept {
650 return iterator(data() + size());
651 }
652
655 GAIA_NODISCARD auto end() const noexcept {
656 return const_iterator(data() + size());
657 }
658
661 GAIA_NODISCARD auto cend() const noexcept {
662 return const_iterator(data() + size());
663 }
664
667 GAIA_NODISCARD auto rend() noexcept {
668 return reverse_iterator(begin());
669 }
670
673 GAIA_NODISCARD auto rend() const noexcept {
675 }
676
679 GAIA_NODISCARD auto crend() const noexcept {
681 }
682
686 GAIA_NODISCARD bool operator==(const darr_ext& other) const noexcept {
687 if (m_cnt != other.m_cnt)
688 return false;
689 const size_type n = size();
690 for (size_type i = 0; i < n; ++i)
691 if (!(operator[](i) == other[i]))
692 return false;
693 return true;
694 }
695
699 GAIA_NODISCARD constexpr bool operator!=(const darr_ext& other) const noexcept {
700 return !operator==(other);
701 }
702 };
703
705 namespace detail {
706 template <typename T, uint32_t N, uint32_t... I>
707 darr_ext<std::remove_cv_t<T>, N> to_sarray_impl(T (&a)[N], std::index_sequence<I...> /*no_name*/) {
708 return {{a[I]...}};
709 }
710 } // namespace detail
712
718 template <typename T, uint32_t N>
719 darr_ext<std::remove_cv_t<T>, N> to_sarray(T (&a)[N]) {
720 return detail::to_sarray_impl(a, std::make_index_sequence<N>{});
721 }
722
723 } // namespace cnt
724
725} // namespace gaia
Array of elements of type.
Definition darray_ext_impl.h:31
void pop_back() noexcept
Removes the last element.
Definition darray_ext_impl.h:400
GAIA_NODISCARD auto end() const noexcept
Returns an iterator one past the last element.
Definition darray_ext_impl.h:655
GAIA_NODISCARD size_type size() const noexcept
Returns the number of elements.
Definition darray_ext_impl.h:561
GAIA_NODISCARD decltype(auto) front() const noexcept
Accesses the first element.
Definition darray_ext_impl.h:592
darr_ext(darr_ext &&other) noexcept
Move-constructs a container.
Definition darray_ext_impl.h:137
darr_ext & operator=(darr_ext &&other) noexcept
Move-assigns the container.
Definition darray_ext_impl.h:186
core::reverse_iterator< iterator, difference_type > reverse_iterator
Mutable reverse random-access iterator type.
Definition darray_ext_impl.h:57
darr_ext(size_type count)
Constructs a container with the requested number of value-initialized elements.
Definition darray_ext_impl.h:101
darr_ext & operator=(std::initializer_list< T > il)
Replaces the elements from an initializer list.
Definition darray_ext_impl.h:165
GAIA_NODISCARD size_type max_size() const noexcept
Returns the maximum number of elements supported by this container.
Definition darray_ext_impl.h:579
iterator insert(iterator pos, T &&arg)
Insert the element to the position given by iterator pos.
Definition darray_ext_impl.h:442
void shrink_to_fit()
Reduces allocated storage to match the current size when possible.
Definition darray_ext_impl.h:523
GAIA_NODISCARD auto rbegin() noexcept
Returns a reverse traversal iterator to the last element.
Definition darray_ext_impl.h:631
GAIA_NODISCARD auto rend() noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition darray_ext_impl.h:667
GAIA_NODISCARD auto crbegin() const noexcept
Returns a read-only reverse traversal iterator to the last element.
Definition darray_ext_impl.h:643
const_pointer const_iterator
Read-only random-access iterator type.
Definition darray_ext_impl.h:55
pointer iterator
Mutable random-access iterator type.
Definition darray_ext_impl.h:53
iterator insert(iterator pos, const T &arg)
Insert the element to the position given by iterator pos.
Definition darray_ext_impl.h:414
GAIA_NODISCARD auto rend() const noexcept
Returns the reverse traversal sentinel preceding the first element.
Definition darray_ext_impl.h:673
darr_ext(size_type count, const_reference value)
Constructs a container with copies of a value.
Definition darray_ext_impl.h:95
GAIA_NODISCARD auto cbegin() const noexcept
Returns a read-only iterator to the first element.
Definition darray_ext_impl.h:625
GAIA_NODISCARD decltype(auto) front() noexcept
Accesses the first element.
Definition darray_ext_impl.h:585
void reserve(size_type cap)
Ensures storage for at least the requested number of elements.
Definition darray_ext_impl.h:266
GAIA_NODISCARD auto begin() noexcept
Returns an iterator to the first element.
Definition darray_ext_impl.h:613
iterator erase(iterator first, iterator last) noexcept
Removes the elements in the range [first, last)
Definition darray_ext_impl.h:494
void resize(size_type count, const_reference value, ResizePolicy policy=ResizePolicy::Exact)
Changes the size and initializes new elements from a value.
Definition darray_ext_impl.h:338
core::reverse_iterator< const_iterator, difference_type > const_reverse_iterator
Read-only reverse random-access iterator type.
Definition darray_ext_impl.h:59
darr_ext(InputIt first, InputIt last)
Constructs a container from an iterator range.
Definition darray_ext_impl.h:110
GAIA_NODISCARD auto rbegin() const noexcept
Returns a reverse traversal iterator to the last element.
Definition darray_ext_impl.h:637
void push_back(const T &arg)
Appends an element.
Definition darray_ext_impl.h:360
GAIA_NODISCARD auto end() noexcept
Returns an iterator one past the last element.
Definition darray_ext_impl.h:649
GAIA_NODISCARD constexpr bool operator!=(const darr_ext &other) const noexcept
Checks whether two containers differ.
Definition darray_ext_impl.h:699
darr_ext_detail::size_type size_type
Unsigned type used for sizes and indices.
Definition darray_ext_impl.h:50
static constexpr size_t value_size
Size of one element in bytes.
Definition darray_ext_impl.h:64
darr_ext(std::initializer_list< T > il)
Constructs a container from an initializer list.
Definition darray_ext_impl.h:129
void resize(size_type count, ResizePolicy policy=ResizePolicy::Exact)
Changes the number of elements.
Definition darray_ext_impl.h:289
GAIA_NODISCARD auto cend() const noexcept
Returns a read-only iterator one past the last element.
Definition darray_ext_impl.h:661
GAIA_NODISCARD auto crend() const noexcept
Returns the read-only reverse traversal sentinel preceding the first element.
Definition darray_ext_impl.h:679
auto retain(Func &&func) noexcept
Removes all elements that fail the predicate. The predicate may modify its element but must not chang...
Definition darray_ext_impl.h:552
T * pointer
Mutable element pointer type.
Definition darray_ext_impl.h:42
darr_ext(const darr_ext &other)
Copy-constructs a container.
Definition darray_ext_impl.h:133
void clear() noexcept
Removes all elements.
Definition darray_ext_impl.h:518
static constexpr size_type extent
Fixed capacity of the container.
Definition darray_ext_impl.h:66
darr_ext & operator=(const darr_ext &other)
Copy-assigns the container.
Definition darray_ext_impl.h:173
darr_ext_detail::difference_type difference_type
Type used for iterator differences.
Definition darray_ext_impl.h:48
GAIA_NODISCARD decltype(auto) back() noexcept
Accesses the last element.
Definition darray_ext_impl.h:599
GAIA_NODISCARD const_pointer data() const noexcept
Returns a pointer to the element storage.
Definition darray_ext_impl.h:242
GAIA_NODISCARD decltype(auto) operator[](size_type pos) noexcept
Accesses an element without bounds checking in optimized builds.
Definition darray_ext_impl.h:249
iterator erase(iterator pos) noexcept
Removes the element at pos.
Definition darray_ext_impl.h:469
decltype(auto) emplace_back(Args &&... args)
Constructs and appends an element.
Definition darray_ext_impl.h:375
GAIA_NODISCARD auto begin() const noexcept
Returns an iterator to the first element.
Definition darray_ext_impl.h:619
GAIA_NODISCARD decltype(auto) back() const noexcept
Accesses the last element.
Definition darray_ext_impl.h:606
const T * const_pointer
Read-only element pointer type.
Definition darray_ext_impl.h:44
void push_back(T &&arg)
Appends an element.
Definition darray_ext_impl.h:366
GAIA_NODISCARD bool operator==(const darr_ext &other) const noexcept
Compares two containers element by element.
Definition darray_ext_impl.h:686
GAIA_NODISCARD pointer data() noexcept
Returns a pointer to the element storage.
Definition darray_ext_impl.h:236
static constexpr uint32_t allocated_bytes
Number of bytes reserved by the inline storage.
Definition darray_ext_impl.h:68
GAIA_NODISCARD bool empty() const noexcept
Checks whether the container has no elements.
Definition darray_ext_impl.h:567
GAIA_NODISCARD size_type capacity() const noexcept
Returns the number of elements that fit without reallocation.
Definition darray_ext_impl.h:573
Random-access iterator that traverses an underlying iterator in reverse. The stored iterator denotes ...
Definition iterator.h:24
View policy for accessing and storing data in the AoS way. Good for random access and when accessing ...
Definition data_layout_policy.h:160
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:173
std::add_pointer_t< ValueType > TargetCastType
Pointer type used to address stored values.
Definition data_layout_policy.h:162
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:234
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:226