34 using const_reference =
const T&;
36 using const_pointer =
const T*;
39 using size_type = darr_ext_detail::size_type;
41 using iterator = pointer;
42 using const_iterator = const_pointer;
45 static constexpr size_t value_size =
sizeof(T);
46 static constexpr size_type extent =
N;
47 static constexpr uint32_t allocated_bytes = view_policy::get_min_byte_size(0,
N);
57 size_type m_cnt = size_type(0);
59 size_type m_cap = extent;
62 const auto cnt = size();
63 const auto cap = capacity();
66 if GAIA_LIKELY (cnt <
cap)
71 m_cap = (
cap * 3 + 1) / 2;
73 if GAIA_UNLIKELY (m_pDataHeap ==
nullptr) {
76 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pDataHeap, m_cap, cnt);
77 mem::move_elements<T, false>(m_pDataHeap, m_data, cnt, 0, m_cap,
cap);
82 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pDataHeap, m_cap, cnt);
83 mem::move_elements<T, false>(m_pDataHeap,
pDataOld, cnt, 0, m_cap,
cap);
87 m_pData = m_pDataHeap;
94 darr_ext(size_type count, const_reference value) {
102 template <
typename InputIt>
104 const auto count = (size_type)core::distance(first, last);
107 if constexpr (std::is_pointer_v<InputIt>) {
108 for (size_type
i = 0;
i < count; ++
i)
109 operator[](
i) = first[
i];
110 }
else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
111 for (size_type
i = 0;
i < count; ++
i)
112 operator[](
i) = *(first[
i]);
115 for (
auto it = first;
it != last; ++
it)
116 operator[](++
i) = *
it;
125 GAIA_ASSERT(core::addressof(other) !=
this);
128 if (other.m_pDataHeap ==
nullptr) {
129 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_data, extent, other.size());
130 mem::move_elements<T, false>(m_data, other.m_data, other.size(), 0, extent, other.extent);
131 GAIA_MEM_SANI_DEL_BLOCK(value_size, other.m_data, extent, other.size());
132 m_pDataHeap =
nullptr;
135 m_pDataHeap = other.m_pDataHeap;
136 m_pData = m_pDataHeap;
142 other.m_pDataHeap =
nullptr;
143 other.m_pData = other.m_data;
144 other.m_cnt = size_type(0);
145 other.m_cap = extent;
148 darr_ext& operator=(std::initializer_list<T>
il) {
154 GAIA_ASSERT(core::addressof(other) !=
this);
156 resize(other.size());
157 mem::copy_elements<T, false>(
158 m_pData, (
const uint8_t*)other.m_pData, other.size(), 0, capacity(), other.capacity());
164 GAIA_ASSERT(core::addressof(other) !=
this);
170 if (other.m_pDataHeap ==
nullptr) {
171 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_data, extent, other.size());
172 mem::move_elements<T, false>(m_data, other.m_data, other.size(), 0, extent, other.extent);
173 GAIA_MEM_SANI_DEL_BLOCK(value_size, other.m_data, extent, other.size());
174 m_pDataHeap =
nullptr;
177 m_pDataHeap = other.m_pDataHeap;
178 m_pData = m_pDataHeap;
184 other.m_pDataHeap =
nullptr;
185 other.m_pData = other.m_data;
186 other.m_cnt = size_type(0);
187 other.m_cap = extent;
196 GAIA_CLANG_WARNING_PUSH()
198 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
200 GAIA_NODISCARD pointer data()
noexcept {
201 return reinterpret_cast<pointer
>(m_pData);
204 GAIA_NODISCARD const_pointer data()
const noexcept {
205 return reinterpret_cast<const_pointer
>(m_pData);
208 GAIA_NODISCARD
decltype(
auto)
operator[](size_type pos)
noexcept {
209 GAIA_ASSERT(pos < size());
210 return view_policy::set({(
typename view_policy::TargetCastType)m_pData, size()}, pos);
213 GAIA_NODISCARD
decltype(
auto)
operator[](size_type pos)
const noexcept {
214 GAIA_ASSERT(pos < size());
215 return view_policy::get({(
typename view_policy::TargetCastType)m_pData, size()}, pos);
218 GAIA_CLANG_WARNING_POP()
220 void reserve(size_type
cap) {
226 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pDataHeap,
cap, m_cnt);
228 mem::move_elements<T, false>(m_pDataHeap,
pDataOld, m_cnt, 0,
cap, m_cap);
231 mem::move_elements<T, false>(m_pDataHeap, m_data, m_cnt, 0,
cap, m_cap);
232 GAIA_MEM_SANI_DEL_BLOCK(value_size, m_data, m_cap, m_cnt);
236 m_pData = m_pDataHeap;
239 void resize(size_type count) {
246 core::call_dtor_n(&data()[count], m_cnt - count);
247 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt, m_cnt - count);
254 if (count <= m_cap) {
256 GAIA_MEM_SANI_PUSH_N(value_size, data(), m_cap, m_cnt, count - m_cnt);
257 core::call_ctor_n(&data()[m_cnt], count - m_cnt);
265 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pDataHeap, count, count);
266 auto*
pDataNew =
reinterpret_cast<pointer
>(m_pDataHeap);
268 mem::move_elements<T, false>(m_pDataHeap,
pDataOld, m_cnt, 0, count, m_cap);
269 core::call_ctor_n(&
pDataNew[m_cnt], count - m_cnt);
272 mem::move_elements<T, false>(m_pDataHeap, m_data, m_cnt, 0, count, m_cap);
273 GAIA_MEM_SANI_DEL_BLOCK(value_size, m_data, m_cap, m_cnt);
278 m_pData = m_pDataHeap;
281 void resize(size_type count, const_reference value) {
285 if constexpr (std::is_copy_constructible_v<value_type>) {
291 operator[](
i) = value;
295 void push_back(
const T& arg) {
298 GAIA_MEM_SANI_PUSH(value_size, data(), m_cap, m_cnt);
299 auto* ptr = &data()[m_cnt++];
300 core::call_ctor(ptr, arg);
303 void push_back(T&& arg) {
306 GAIA_MEM_SANI_PUSH(value_size, data(), m_cap, m_cnt);
307 auto* ptr = &data()[m_cnt++];
308 core::call_ctor(ptr, GAIA_MOV(arg));
311 template <
typename...
Args>
312 decltype(
auto) emplace_back(
Args&&...
args) {
315 GAIA_MEM_SANI_PUSH(value_size, data(), m_cap, m_cnt);
316 auto* ptr = &data()[m_cnt++];
317 core::call_ctor(ptr, GAIA_FWD(
args)...);
318 return (reference)*ptr;
321 void pop_back()
noexcept {
322 GAIA_ASSERT(!empty());
324 auto* ptr = &data()[m_cnt - 1];
325 core::call_dtor(ptr);
326 GAIA_MEM_SANI_POP(value_size, data(), m_cap, m_cnt);
334 iterator
insert(iterator pos,
const T& arg) {
335 GAIA_ASSERT(pos >= data());
336 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
338 const auto idxSrc = (size_type)core::distance(begin(), pos);
340 const auto idxDst = (size_type)core::distance(begin(), end()) + 1;
342 GAIA_MEM_SANI_PUSH(value_size, data(), m_cap, m_cnt);
343 mem::shift_elements_right<T, false>(m_pData,
idxDst,
idxSrc, m_cap);
344 auto* ptr = &data()[
idxSrc];
345 core::call_ctor(ptr, arg);
349 return iterator(ptr);
356 GAIA_ASSERT(pos >= data());
357 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
359 const auto idxSrc = (size_type)core::distance(begin(), pos);
361 const auto idxDst = (size_type)core::distance(begin(), end());
363 GAIA_MEM_SANI_PUSH(value_size, data(), m_cap, m_cnt);
364 mem::shift_elements_right<T, false>(m_pData,
idxDst,
idxSrc, m_cap);
365 auto* ptr = &data()[
idxSrc];
366 core::call_ctor(ptr, GAIA_MOV(arg));
370 return iterator(ptr);
375 iterator
erase(iterator pos)
noexcept {
376 GAIA_ASSERT(pos >= data());
377 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
382 const auto idxSrc = (size_type)core::distance(begin(), pos);
383 const auto idxDst = (size_type)core::distance(begin(), end()) - 1;
385 mem::shift_elements_left<T, false>(m_pData,
idxDst,
idxSrc, m_cap);
387 auto* ptr = &data()[m_cnt - 1];
388 core::call_dtor(ptr);
389 GAIA_MEM_SANI_POP(value_size, data(), m_cap, m_cnt);
393 return iterator(&data()[
idxSrc]);
399 iterator
erase(iterator first, iterator last)
noexcept {
400 GAIA_ASSERT(first >= data())
401 GAIA_ASSERT(empty() || (first < iterator(data() + size())));
402 GAIA_ASSERT(last > first);
403 GAIA_ASSERT(last <= iterator(data() + size()));
408 const auto idxSrc = (size_type)core::distance(begin(), first);
409 const auto idxDst = size();
410 const auto cnt = (size_type)(last - first);
412 mem::shift_elements_left_fast<T, false>(m_pData,
idxDst,
idxSrc, cnt, m_cap);
414 core::call_dtor_n(&data()[m_cnt - cnt], cnt);
415 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt, cnt);
419 return iterator(&data()[
idxSrc]);
426 void shrink_to_fit() {
427 const auto cap = capacity();
428 const auto cnt = size();
433 if (m_pDataHeap !=
nullptr) {
434 auto* pDataOld = m_pDataHeap;
437 mem::move_elements<T, false>(m_data, pDataOld, cnt, 0);
441 m_pDataHeap = view_policy::template alloc<Allocator>(m_cap = cnt);
442 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pDataHeap, m_cap, m_cnt);
443 mem::move_elements<T, false>(m_pDataHeap, pDataOld, cnt, 0);
444 m_pData = m_pDataHeap;
447 GAIA_MEM_SANI_DEL_BLOCK(value_size, pDataOld, cap, cnt);
448 view_policy::template free<Allocator>(pDataOld);
456 template <
typename Func>
463 if (func(
operator[](
idxSrc))) {
466 mem::move_element<T, false>(ptr, ptr,
idxDst,
idxSrc, m_cap, m_cap);
468 core::call_dtor(
ptr2);
472 auto* ptr = &data()[
idxSrc];
473 core::call_dtor(ptr);
480 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt,
erased);
490 GAIA_NODISCARD
bool empty() const noexcept {
494 GAIA_NODISCARD size_type capacity() const noexcept {
498 GAIA_NODISCARD size_type max_size() const noexcept {
502 GAIA_NODISCARD
decltype(
auto) front() noexcept {
503 GAIA_ASSERT(!empty());
504 return (reference)*begin();
507 GAIA_NODISCARD
decltype(
auto) front() const noexcept {
508 GAIA_ASSERT(!empty());
509 return (const_reference)*begin();
512 GAIA_NODISCARD
decltype(
auto) back() noexcept {
513 GAIA_ASSERT(!empty());
514 return (reference) operator[](m_cnt - 1);
517 GAIA_NODISCARD
decltype(
auto) back() const noexcept {
518 GAIA_ASSERT(!empty());
519 return (const_reference) operator[](m_cnt - 1);
522 GAIA_NODISCARD
auto begin() noexcept {
523 return iterator(data());
526 GAIA_NODISCARD
auto begin() const noexcept {
527 return const_iterator(data());
530 GAIA_NODISCARD
auto cbegin() const noexcept {
531 return const_iterator(data());
534 GAIA_NODISCARD
auto rbegin() noexcept {
535 return iterator((pointer)&back());
538 GAIA_NODISCARD
auto rbegin() const noexcept {
539 return const_iterator((const_pointer)&back());
542 GAIA_NODISCARD
auto crbegin() const noexcept {
543 return const_iterator((const_pointer)&back());
546 GAIA_NODISCARD
auto end() noexcept {
547 return iterator(data() + size());
550 GAIA_NODISCARD
auto end() const noexcept {
551 return const_iterator(data() + size());
554 GAIA_NODISCARD
auto cend() const noexcept {
555 return const_iterator(data() + size());
558 GAIA_NODISCARD
auto rend() noexcept {
559 return iterator(data() - 1);
562 GAIA_NODISCARD
auto rend() const noexcept {
563 return const_iterator(data() - 1);
566 GAIA_NODISCARD
auto crend() const noexcept {
567 return const_iterator(data() - 1);
570 GAIA_NODISCARD
bool operator==(
const darr_ext& other)
const noexcept {
571 if (m_cnt != other.m_cnt)
573 const size_type n = size();
574 for (size_type i = 0; i < n; ++i)
575 if (!(
operator[](i) == other[i]))
580 GAIA_NODISCARD
constexpr bool operator!=(
const darr_ext& other)
const noexcept {
581 return !operator==(other);