diff --git a/include/containers/basalt_darray.h b/include/containers/basalt_darray.h index 7d17521..73fad81 100644 --- a/include/containers/basalt_darray.h +++ b/include/containers/basalt_darray.h @@ -60,6 +60,8 @@ namespace basalt T& peek_front(void) noexcept; const T& peek_front(void) const noexcept; + const bool contains(const T& val) const noexcept; + T* m_pdata = nullptr; size_t m_nelements = 0; size_t m_ncapacity = 0; @@ -83,12 +85,13 @@ namespace basalt return *this; this->~darray(); this->m_pdata = mem::allocT(src.m_nelements, src.m_tag); - BASSERT_ERROR(this->m_pdata != nullptr, return; , "Assertion %s failed at %s:%d\n\tMemory allocation failed for allocation size %u\n\t%s | %s | %u"); + BASSERT_ERROR(this->m_pdata != nullptr, return *this; , "Assertion %s failed at %s:%d\n\tMemory allocation failed for allocation size %u\n\t%s | %s | %u"); this->m_tag = src.m_tag; this->m_ncapacity = src.m_nelements; this->m_nelements = src.m_nelements; memcpy(this->m_pdata, src.m_pdata, sizeof(T)*this->m_nelements); BTRACE("darray<%s> %p was copied to %p (%p)\n", typeid(T).name(), &src, this, this->m_pdata); + return *this; } template @@ -188,6 +191,9 @@ namespace basalt { if (this->m_pdata != nullptr) { + if (!std::is_trivially_destructible_v) + for (size_t i = 0; i < m_nelements; ++i) + m_pdata[i].~T(); mem::dealloc(this->m_pdata, this->m_ncapacity * sizeof(T), this->m_tag); BTRACE("darray<%s> %p destroyed %p\n", typeid(T).name(), this, this->m_pdata); } @@ -255,10 +261,9 @@ namespace basalt if ((this->m_nelements + new_size) > this->m_ncapacity) this->reserve(new_size * 2); // Call destructor for objects outside of the new size - if (!std::is_trivially_destructible_v) - if (new_size < m_nelements) - for (size_t i = new_size; i < this->m_nelements; ++i) - this->m_pdata[i].~T(); + if (new_size < m_nelements) + for (size_t i = new_size; i < this->m_nelements; ++i) + this->m_pdata[i].~T(); this->m_nelements = new_size; } @@ -268,23 +273,33 @@ namespace basalt template inline void darray::reserve(size_t new_capacity) noexcept { - if (new_capacity < this->m_ncapacity) + if (new_capacity <= this->m_ncapacity) return; T* tmp = mem::allocT(new_capacity, this->m_tag); - if (std::is_trivially_copy_assignable_v) + if constexpr (std::is_trivially_copy_assignable_v) + { memcpy(tmp, this->m_pdata, this->m_nelements * sizeof(T)); - else if (std::is_move_assignable_v) - for (size_t i = 0; i < this->m_nelements; ++i) - tmp[i] = std::move(this->m_pdata[i]); - else if (std::is_move_constructible_v) + } + else if constexpr (std::is_move_constructible_v) + { for (size_t i = 0; i < this->m_nelements; ++i) new (tmp + i) T(std::move(this->m_pdata[i])); - else if (std::is_copy_assignable_v) + } + else if constexpr (std::is_move_assignable_v) + { + for (size_t i = 0; i < this->m_nelements; ++i) + tmp[i] = std::move(this->m_pdata[i]); + } + else if constexpr (std::is_copy_constructible_v) + { + for (size_t i = 0; i < this->m_nelements; ++i) + new (tmp + i) T(this->m_pdata[i]); + } + else if constexpr (std::is_copy_assignable_v) + { for (size_t i = 0; i < this->m_nelements; ++i) tmp[i] = this->m_pdata[i]; - else if (std::is_copy_constructible_v) - for (size_t i = 0; i < this->m_nelements; ++i) - new (tmp+i) T(this->m_pdata[i]); + } else { BERROR("Can not resize object dynarray<%s>\n\tIt is not trivially copyable, copy assignable, copy constructible, move assignable or move constructable\n", typeid(T).name()); @@ -292,9 +307,8 @@ namespace basalt return; } - if (!std::is_trivially_destructible_v) - for (size_t i = 0; i < this->m_nelements; ++i) - this->m_pdata[i].~T(); + for (size_t i = 0; i < this->m_nelements; ++i) + this->m_pdata[i].~T(); mem::dealloc(this->m_pdata, this->m_ncapacity*sizeof(T), this->m_tag); BTRACE("darray<%s> %p Resized from %llu (%p) to %llu (%p)\n", typeid(T).name(), this, this->m_ncapacity, this->m_pdata, new_capacity, tmp); this->m_ncapacity = new_capacity; @@ -306,18 +320,18 @@ namespace basalt if (this->m_nelements == this->m_ncapacity) return; T* tmp = mem::allocT(this->m_nelements, this->m_tag); - if (std::is_trivially_copy_assignable_v) + if constexpr (std::is_trivially_copy_assignable_v) memcpy(tmp, this->m_pdata, this->m_nelements * sizeof(T)); - else if (std::is_move_assignable_v) + else if constexpr(std::is_move_assignable_v) for (size_t i = 0; i < this->m_nelements; ++i) tmp[i] = std::move(this->m_pdata[i]); - else if (std::is_move_constructible_v) + else if constexpr (std::is_move_constructible_v) for (size_t i = 0; i < this->m_nelements; ++i) new (tmp + i) T(std::move(this->m_pdata[i])); - else if (std::is_copy_assignable_v) + else if constexpr (std::is_copy_assignable_v) for (size_t i = 0; i < this->m_nelements; ++i) tmp[i] = this->m_pdata[i]; - else if (std::is_copy_constructible_v) + else if constexpr (std::is_copy_constructible_v) for (size_t i = 0; i < this->m_nelements; ++i) new (tmp + i) T(this->m_pdata[i]); else @@ -327,9 +341,8 @@ namespace basalt return; } - if (!std::is_trivially_destructible_v) - for (size_t i = 0; i < this->m_nelements; ++i) - this->m_pdata[i].~T(); + for (size_t i = 0; i < this->m_nelements; ++i) + this->m_pdata[i].~T(); mem::dealloc(this->m_pdata, this->m_ncapacity * sizeof(T), this->m_tag); BTRACE("darray<%s> %p (%p) Shrink fit to %llu (%p)\n", typeid(T).name(), this, this->m_pdata, this->m_nelements, tmp); this->m_ncapacity = this->m_nelements; @@ -341,11 +354,11 @@ namespace basalt { if ((this->m_nelements + 1) > this->m_ncapacity) this->expand(this->m_ncapacity < 1 ? 1 : this->m_ncapacity); - if (std::is_trivially_copyable_v) + if constexpr (std::is_trivially_copyable_v) memcpy(this->m_pdata + this->m_nelements, &val, sizeof(T)); - else if (std::is_copy_constructible_v) + else if constexpr (std::is_copy_constructible_v) new (this->m_pdata + this->m_nelements) T(val); - else if (std::is_copy_assignable_v) + else if constexpr (std::is_copy_assignable_v) this->m_pdata[this->m_nelements] = val; else { @@ -360,11 +373,11 @@ namespace basalt { if ((this->m_nelements + 1) > this->m_ncapacity) this->expand(this->m_ncapacity < 1 ? 1 : this->m_ncapacity); - if (std::is_trivially_move_assignable_v) + if constexpr (std::is_trivially_move_assignable_v) memcpy(this->m_pdata + this->m_nelements, &val, sizeof(T)); - else if (std::is_move_constructible_v) + else if constexpr (std::is_move_constructible_v) new (this->m_pdata + this->m_nelements) T(std::move(val)); - else if (std::is_move_assignable_v) + else if constexpr (std::is_move_assignable_v) this->m_pdata[this->m_nelements] = std::move(val); else { @@ -381,16 +394,16 @@ namespace basalt nelements = nelements < 0 ? -nelements : nelements; if ((this->m_nelements + nelements) > this->m_ncapacity) this->expand(nelements + this->m_nelements + 1); - if (std::is_trivially_copyable_v) + if constexpr (std::is_trivially_copyable_v) { memcpy(this->m_pdata + this->m_nelements, beg, sizeof(T) * nelements); } - else if (std::is_copy_assignable_v) + else if constexpr (std::is_copy_assignable_v) { for (size_t i = 0; i < nelements; ++i) this->m_pdata[this->m_nelements + i] = beg[i]; } - else if (std::is_copy_constructible_v) + else if constexpr (std::is_copy_constructible_v) { for (size_t i = 0; i < nelements; ++i) new (this->m_pdata + this->m_nelements + i) T(beg[i]); @@ -454,8 +467,7 @@ namespace basalt idx = 0; darray tmp = std::move(this->m_pdata[idx]); --this->m_nelements; - if (!std::is_trivially_destructible_v) - this->m_pdata[this->m_nelements].~T(); + this->m_pdata[this->m_nelements].~T(); return std::move(tmp); }