Made some of the if statements constexpr to dodge compiler errors for non-copyable or non-movable objects

This commit is contained in:
2025-07-07 22:43:13 +10:00
parent 1668d74934
commit ab95363f51

View File

@@ -60,6 +60,8 @@ namespace basalt
T& peek_front(void) noexcept; T& peek_front(void) noexcept;
const T& peek_front(void) const noexcept; const T& peek_front(void) const noexcept;
const bool contains(const T& val) const noexcept;
T* m_pdata = nullptr; T* m_pdata = nullptr;
size_t m_nelements = 0; size_t m_nelements = 0;
size_t m_ncapacity = 0; size_t m_ncapacity = 0;
@@ -83,12 +85,13 @@ namespace basalt
return *this; return *this;
this->~darray(); this->~darray();
this->m_pdata = mem::allocT<T>(src.m_nelements, src.m_tag); this->m_pdata = mem::allocT<T>(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_tag = src.m_tag;
this->m_ncapacity = src.m_nelements; this->m_ncapacity = src.m_nelements;
this->m_nelements = src.m_nelements; this->m_nelements = src.m_nelements;
memcpy(this->m_pdata, src.m_pdata, sizeof(T)*this->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); BTRACE("darray<%s> %p was copied to %p (%p)\n", typeid(T).name(), &src, this, this->m_pdata);
return *this;
} }
template<typename T> template<typename T>
@@ -188,6 +191,9 @@ namespace basalt
{ {
if (this->m_pdata != nullptr) if (this->m_pdata != nullptr)
{ {
if (!std::is_trivially_destructible_v<T>)
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); 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); 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) if ((this->m_nelements + new_size) > this->m_ncapacity)
this->reserve(new_size * 2); this->reserve(new_size * 2);
// Call destructor for objects outside of the new size // Call destructor for objects outside of the new size
if (!std::is_trivially_destructible_v<T>) if (new_size < m_nelements)
if (new_size < m_nelements) for (size_t i = new_size; i < this->m_nelements; ++i)
for (size_t i = new_size; i < this->m_nelements; ++i) this->m_pdata[i].~T();
this->m_pdata[i].~T();
this->m_nelements = new_size; this->m_nelements = new_size;
} }
@@ -268,23 +273,33 @@ namespace basalt
template<typename T> template<typename T>
inline void darray<T>::reserve(size_t new_capacity) noexcept inline void darray<T>::reserve(size_t new_capacity) noexcept
{ {
if (new_capacity < this->m_ncapacity) if (new_capacity <= this->m_ncapacity)
return; return;
T* tmp = mem::allocT<T>(new_capacity, this->m_tag); T* tmp = mem::allocT<T>(new_capacity, this->m_tag);
if (std::is_trivially_copy_assignable_v<T>) if constexpr (std::is_trivially_copy_assignable_v<T>)
{
memcpy(tmp, this->m_pdata, this->m_nelements * sizeof(T)); memcpy(tmp, this->m_pdata, this->m_nelements * sizeof(T));
else if (std::is_move_assignable_v<T>) }
for (size_t i = 0; i < this->m_nelements; ++i) else if constexpr (std::is_move_constructible_v<T>)
tmp[i] = std::move(this->m_pdata[i]); {
else if (std::is_move_constructible_v<T>)
for (size_t i = 0; i < this->m_nelements; ++i) for (size_t i = 0; i < this->m_nelements; ++i)
new (tmp + i) T(std::move(this->m_pdata[i])); new (tmp + i) T(std::move(this->m_pdata[i]));
else if (std::is_copy_assignable_v<T>) }
else if constexpr (std::is_move_assignable_v<T>)
{
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<T>)
{
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<T>)
{
for (size_t i = 0; i < this->m_nelements; ++i) for (size_t i = 0; i < this->m_nelements; ++i)
tmp[i] = this->m_pdata[i]; tmp[i] = this->m_pdata[i];
else if (std::is_copy_constructible_v<T>) }
for (size_t i = 0; i < this->m_nelements; ++i)
new (tmp+i) T(this->m_pdata[i]);
else 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()); 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; return;
} }
if (!std::is_trivially_destructible_v<T>) for (size_t i = 0; i < this->m_nelements; ++i)
for (size_t i = 0; i < this->m_nelements; ++i) this->m_pdata[i].~T();
this->m_pdata[i].~T();
mem::dealloc(this->m_pdata, this->m_ncapacity*sizeof(T), this->m_tag); 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); 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; this->m_ncapacity = new_capacity;
@@ -306,18 +320,18 @@ namespace basalt
if (this->m_nelements == this->m_ncapacity) if (this->m_nelements == this->m_ncapacity)
return; return;
T* tmp = mem::allocT<T>(this->m_nelements, this->m_tag); T* tmp = mem::allocT<T>(this->m_nelements, this->m_tag);
if (std::is_trivially_copy_assignable_v<T>) if constexpr (std::is_trivially_copy_assignable_v<T>)
memcpy(tmp, this->m_pdata, this->m_nelements * sizeof(T)); memcpy(tmp, this->m_pdata, this->m_nelements * sizeof(T));
else if (std::is_move_assignable_v<T>) else if constexpr(std::is_move_assignable_v<T>)
for (size_t i = 0; i < this->m_nelements; ++i) for (size_t i = 0; i < this->m_nelements; ++i)
tmp[i] = std::move(this->m_pdata[i]); tmp[i] = std::move(this->m_pdata[i]);
else if (std::is_move_constructible_v<T>) else if constexpr (std::is_move_constructible_v<T>)
for (size_t i = 0; i < this->m_nelements; ++i) for (size_t i = 0; i < this->m_nelements; ++i)
new (tmp + i) T(std::move(this->m_pdata[i])); new (tmp + i) T(std::move(this->m_pdata[i]));
else if (std::is_copy_assignable_v<T>) else if constexpr (std::is_copy_assignable_v<T>)
for (size_t i = 0; i < this->m_nelements; ++i) for (size_t i = 0; i < this->m_nelements; ++i)
tmp[i] = this->m_pdata[i]; tmp[i] = this->m_pdata[i];
else if (std::is_copy_constructible_v<T>) else if constexpr (std::is_copy_constructible_v<T>)
for (size_t i = 0; i < this->m_nelements; ++i) for (size_t i = 0; i < this->m_nelements; ++i)
new (tmp + i) T(this->m_pdata[i]); new (tmp + i) T(this->m_pdata[i]);
else else
@@ -327,9 +341,8 @@ namespace basalt
return; return;
} }
if (!std::is_trivially_destructible_v<T>) for (size_t i = 0; i < this->m_nelements; ++i)
for (size_t i = 0; i < this->m_nelements; ++i) this->m_pdata[i].~T();
this->m_pdata[i].~T();
mem::dealloc(this->m_pdata, this->m_ncapacity * sizeof(T), this->m_tag); 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); 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; this->m_ncapacity = this->m_nelements;
@@ -341,11 +354,11 @@ namespace basalt
{ {
if ((this->m_nelements + 1) > this->m_ncapacity) if ((this->m_nelements + 1) > this->m_ncapacity)
this->expand(this->m_ncapacity < 1 ? 1 : this->m_ncapacity); this->expand(this->m_ncapacity < 1 ? 1 : this->m_ncapacity);
if (std::is_trivially_copyable_v<T>) if constexpr (std::is_trivially_copyable_v<T>)
memcpy(this->m_pdata + this->m_nelements, &val, sizeof(T)); memcpy(this->m_pdata + this->m_nelements, &val, sizeof(T));
else if (std::is_copy_constructible_v<T>) else if constexpr (std::is_copy_constructible_v<T>)
new (this->m_pdata + this->m_nelements) T(val); new (this->m_pdata + this->m_nelements) T(val);
else if (std::is_copy_assignable_v<T>) else if constexpr (std::is_copy_assignable_v<T>)
this->m_pdata[this->m_nelements] = val; this->m_pdata[this->m_nelements] = val;
else else
{ {
@@ -360,11 +373,11 @@ namespace basalt
{ {
if ((this->m_nelements + 1) > this->m_ncapacity) if ((this->m_nelements + 1) > this->m_ncapacity)
this->expand(this->m_ncapacity < 1 ? 1 : this->m_ncapacity); this->expand(this->m_ncapacity < 1 ? 1 : this->m_ncapacity);
if (std::is_trivially_move_assignable_v<T>) if constexpr (std::is_trivially_move_assignable_v<T>)
memcpy(this->m_pdata + this->m_nelements, &val, sizeof(T)); memcpy(this->m_pdata + this->m_nelements, &val, sizeof(T));
else if (std::is_move_constructible_v<T>) else if constexpr (std::is_move_constructible_v<T>)
new (this->m_pdata + this->m_nelements) T(std::move(val)); new (this->m_pdata + this->m_nelements) T(std::move(val));
else if (std::is_move_assignable_v<T>) else if constexpr (std::is_move_assignable_v<T>)
this->m_pdata[this->m_nelements] = std::move(val); this->m_pdata[this->m_nelements] = std::move(val);
else else
{ {
@@ -381,16 +394,16 @@ namespace basalt
nelements = nelements < 0 ? -nelements : nelements; nelements = nelements < 0 ? -nelements : nelements;
if ((this->m_nelements + nelements) > this->m_ncapacity) if ((this->m_nelements + nelements) > this->m_ncapacity)
this->expand(nelements + this->m_nelements + 1); this->expand(nelements + this->m_nelements + 1);
if (std::is_trivially_copyable_v<T>) if constexpr (std::is_trivially_copyable_v<T>)
{ {
memcpy(this->m_pdata + this->m_nelements, beg, sizeof(T) * nelements); memcpy(this->m_pdata + this->m_nelements, beg, sizeof(T) * nelements);
} }
else if (std::is_copy_assignable_v<T>) else if constexpr (std::is_copy_assignable_v<T>)
{ {
for (size_t i = 0; i < nelements; ++i) for (size_t i = 0; i < nelements; ++i)
this->m_pdata[this->m_nelements + i] = beg[i]; this->m_pdata[this->m_nelements + i] = beg[i];
} }
else if (std::is_copy_constructible_v<T>) else if constexpr (std::is_copy_constructible_v<T>)
{ {
for (size_t i = 0; i < nelements; ++i) for (size_t i = 0; i < nelements; ++i)
new (this->m_pdata + this->m_nelements + i) T(beg[i]); new (this->m_pdata + this->m_nelements + i) T(beg[i]);
@@ -454,8 +467,7 @@ namespace basalt
idx = 0; idx = 0;
darray<T> tmp = std::move(this->m_pdata[idx]); darray<T> tmp = std::move(this->m_pdata[idx]);
--this->m_nelements; --this->m_nelements;
if (!std::is_trivially_destructible_v<T>) this->m_pdata[this->m_nelements].~T();
this->m_pdata[this->m_nelements].~T();
return std::move(tmp); return std::move(tmp);
} }