29 using const_reference =
const T&;
31 using const_pointer =
const T*;
36 using iterator = pointer;
37 using const_iterator = const_pointer;
40 static constexpr size_t value_size =
sizeof(T);
48 const auto cnt = size();
49 const auto cap = capacity();
52 if GAIA_LIKELY (
cap != 0 && cnt <
cap)
56 if GAIA_UNLIKELY (m_pData ==
nullptr) {
63 m_cap = (
cap * 3 + 1) / 2;
67 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData, m_cap, cnt);
68 mem::move_elements<T, false>(m_pData,
pDataOld, cnt, 0, m_cap,
cap);
73 darr()
noexcept =
default;
84 template <
typename InputIt>
86 const auto count = (
size_type)core::distance(first, last);
89 if constexpr (std::is_pointer_v<InputIt>) {
91 operator[](
i) = first[
i];
92 }
else if constexpr (std::is_same_v<typename InputIt::iterator_category, core::random_access_iterator_tag>) {
94 operator[](
i) = *(first[
i]);
97 for (
auto it = first;
it != last; ++
it)
98 operator[](++
i) = *
it;
104 darr(
const darr& other):
darr(other.begin(), other.end()) {}
106 darr(
darr&& other)
noexcept: m_pData(other.m_pData), m_cnt(other.m_cnt), m_cap(other.m_cap) {
107 other.m_pData =
nullptr;
112 darr& operator=(std::initializer_list<T>
il) {
117 darr& operator=(
const darr& other) {
118 GAIA_ASSERT(core::addressof(other) !=
this);
120 resize(other.size());
121 mem::copy_elements<T, false>(
122 m_pData, (
const uint8_t*)other.m_pData, other.size(), 0, capacity(), other.capacity());
127 darr& operator=(
darr&& other)
noexcept {
128 GAIA_ASSERT(core::addressof(other) !=
this);
133 m_pData = other.m_pData;
137 other.m_pData =
nullptr;
148 GAIA_CLANG_WARNING_PUSH()
150 GAIA_CLANG_WARNING_DISABLE(
"-Wcast-align")
152 GAIA_NODISCARD pointer data()
noexcept {
153 return reinterpret_cast<pointer
>(m_pData);
156 GAIA_NODISCARD const_pointer data()
const noexcept {
157 return reinterpret_cast<const_pointer
>(m_pData);
160 GAIA_NODISCARD
decltype(
auto)
operator[](
size_type pos)
noexcept {
161 GAIA_ASSERT(pos < size());
162 return view_policy::set({(
typename view_policy::TargetCastType)m_pData, capacity()}, pos);
165 GAIA_NODISCARD
decltype(
auto)
operator[](
size_type pos)
const noexcept {
166 GAIA_ASSERT(pos < size());
167 return view_policy::get({(
typename view_policy::TargetCastType)m_pData, capacity()}, pos);
170 GAIA_CLANG_WARNING_POP()
179 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData,
cap, m_cnt);
180 mem::move_elements<T, false>(m_pData,
pDataOld, m_cnt, 0,
cap, m_cap);
192 if (m_pData ==
nullptr) {
195 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData, count, count);
196 core::call_ctor_n(m_pData, count);
206 core::call_dtor_n(&data()[count], m_cnt - count);
207 GAIA_MEM_SANI_POP_N(value_size, m_pData, m_cap, m_cnt, m_cnt - count);
214 if (count <= m_cap) {
216 GAIA_MEM_SANI_PUSH_N(value_size, m_pData, m_cap, m_cnt, count - m_cnt);
217 core::call_ctor_n(&data()[m_cnt], count - m_cnt);
225 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData, count, count);
227 mem::move_elements<T, false>(m_pData,
pDataOld, m_cnt, 0, count, m_cap);
229 core::call_ctor_n(&data()[m_cnt], count - m_cnt);
237 void resize(
size_type count, const_reference value) {
241 if constexpr (std::is_copy_constructible_v<value_type>) {
247 operator[](
i) = value;
251 void push_back(
const T& arg) {
254 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
255 auto* ptr = &data()[m_cnt++];
256 core::call_ctor(ptr, arg);
259 void push_back(T&& arg) {
262 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
263 auto* ptr = &data()[m_cnt++];
264 core::call_ctor(ptr, GAIA_MOV(arg));
267 template <
typename...
Args>
268 decltype(
auto) emplace_back(
Args&&...
args) {
271 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
272 auto* ptr = &data()[m_cnt++];
273 core::call_ctor(ptr, GAIA_FWD(
args)...);
274 return (reference)*ptr;
277 void pop_back()
noexcept {
278 GAIA_ASSERT(!empty());
280 auto* ptr = &data()[m_cnt - 1];
281 core::call_dtor(ptr);
282 GAIA_MEM_SANI_POP(value_size, m_pData, m_cap, m_cnt);
290 iterator
insert(iterator pos,
const T& arg) {
291 GAIA_ASSERT(pos >= data());
292 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
298 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
299 mem::shift_elements_right<T, false>(m_pData,
idxDst,
idxSrc, m_cap);
300 auto* ptr = &data()[m_cnt];
301 core::call_ctor(ptr, arg);
305 return iterator(&data()[
idxSrc]);
312 GAIA_ASSERT(pos >= data());
313 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
319 GAIA_MEM_SANI_PUSH(value_size, m_pData, m_cap, m_cnt);
320 mem::shift_elements_right<T, false>(m_pData,
idxDst,
idxSrc, m_cap);
321 auto* ptr = &data()[
idxSrc];
322 core::call_ctor(ptr, GAIA_MOV(arg));
326 return iterator(&data()[
idxSrc]);
331 iterator
erase(iterator pos)
noexcept {
332 GAIA_ASSERT(pos >= data());
333 GAIA_ASSERT(empty() || (pos < iterator(data() + size())));
341 mem::shift_elements_left<T, false>(m_pData,
idxDst,
idxSrc, m_cap);
343 auto* ptr = &data()[m_cnt - 1];
344 core::call_dtor(ptr);
345 GAIA_MEM_SANI_POP(value_size, m_pData, m_cap, m_cnt);
349 return iterator(&data()[
idxSrc]);
355 iterator
erase(iterator first, iterator last)
noexcept {
356 GAIA_ASSERT(first >= data())
357 GAIA_ASSERT(empty() || (first < iterator(data() + size())));
358 GAIA_ASSERT(last > first);
359 GAIA_ASSERT(last <= iterator(data() + size()));
365 const auto idxDst = size();
366 const auto cnt = (
size_type)(last - first);
368 mem::shift_elements_left_fast<T, false>(m_pData,
idxDst,
idxSrc, cnt, m_cap);
370 auto* ptr = &data()[m_cnt - cnt];
371 core::call_dtor_n(ptr, cnt);
372 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt, cnt);
376 return iterator(&data()[
idxSrc]);
383 void shrink_to_fit() {
384 const auto cap = capacity();
385 const auto cnt = size();
390 auto* pDataOld = m_pData;
391 m_pData = view_policy::template alloc<Allocator>(m_cap = cnt);
392 GAIA_MEM_SANI_ADD_BLOCK(value_size, m_pData, m_cap, m_cnt);
393 mem::move_elements<T, false>(m_pData, pDataOld, cnt, 0);
394 GAIA_MEM_SANI_DEL_BLOCK(value_size, pDataOld, cap, cnt);
395 view_policy::template free<Allocator>(pDataOld);
401 template <
typename Func>
408 if (func(
operator[](
idxSrc))) {
410 mem::move_element<T, false>(m_pData, m_pData,
idxDst,
idxSrc, m_cap, m_cap);
411 auto* ptr = &data()[
idxSrc];
412 core::call_dtor(ptr);
416 auto* ptr = &data()[
idxSrc];
417 core::call_dtor(ptr);
424 GAIA_MEM_SANI_POP_N(value_size, data(), m_cap, m_cnt,
erased);
434 GAIA_NODISCARD
bool empty() const noexcept {
438 GAIA_NODISCARD size_type capacity() const noexcept {
442 GAIA_NODISCARD size_type max_size() const noexcept {
443 return static_cast<size_type
>(-1);
446 GAIA_NODISCARD
decltype(
auto) front() noexcept {
447 GAIA_ASSERT(!empty());
448 return (reference)*begin();
451 GAIA_NODISCARD
decltype(
auto) front() const noexcept {
452 GAIA_ASSERT(!empty());
453 return (const_reference)*begin();
456 GAIA_NODISCARD
decltype(
auto) back() noexcept {
457 GAIA_ASSERT(!empty());
458 return (reference)(operator[](m_cnt - 1));
461 GAIA_NODISCARD
decltype(
auto) back() const noexcept {
462 GAIA_ASSERT(!empty());
463 return (const_reference) operator[](m_cnt - 1);
466 GAIA_NODISCARD
auto begin() noexcept {
467 return iterator(data());
470 GAIA_NODISCARD
auto begin() const noexcept {
474 GAIA_NODISCARD
auto cbegin() const noexcept {
475 return const_iterator(data());
478 GAIA_NODISCARD
auto rbegin() noexcept {
479 return iterator((pointer)&back());
482 GAIA_NODISCARD
auto rbegin() const noexcept {
483 return const_iterator((const_pointer)&back());
486 GAIA_NODISCARD
auto crbegin() const noexcept {
487 return const_iterator((const_pointer)&back());
490 GAIA_NODISCARD
auto end() noexcept {
491 return iterator(data() + size());
494 GAIA_NODISCARD
auto end() const noexcept {
495 return const_iterator(data() + size());
498 GAIA_NODISCARD
auto cend() const noexcept {
499 return const_iterator(data() + size());
502 GAIA_NODISCARD
auto rend() noexcept {
503 return iterator(data() - 1);
506 GAIA_NODISCARD
auto rend() const noexcept {
507 return const_iterator(data() - 1);
510 GAIA_NODISCARD
auto crend() const noexcept {
511 return const_iterator(data() - 1);
514 GAIA_NODISCARD
bool operator==(
const darr& other)
const noexcept {
515 if (m_cnt != other.m_cnt)
517 const size_type n = size();
518 for (size_type i = 0; i < n; ++i)
519 if (!(
operator[](i) == other[i]))
524 GAIA_NODISCARD
constexpr bool operator!=(
const darr& other)
const noexcept {
525 return !operator==(other);