Add move semantics to core containers.

Adds to SWAP, Variant, StringName, List, CowData and LocalVector.

Co-Authored-By: Lukas Tenbrink <lukas.tenbrink@gmail.com>
This commit is contained in:
lawnjelly 2024-12-19 18:56:40 +00:00
parent cd92ad0f69
commit d549b98c5c
6 changed files with 106 additions and 26 deletions

View file

@ -33,6 +33,7 @@
#include <string.h>
#include <type_traits>
#include <utility>
#include "core/error_macros.h"
#include "core/os/memory.h"
@ -159,28 +160,32 @@ public:
T *p = ptrw();
int len = size();
for (int i = p_index; i < len - 1; i++) {
p[i] = p[i + 1];
p[i] = std::move(p[i + 1]);
};
resize(len - 1);
};
}
Error insert(int p_pos, const T &p_val) {
ERR_FAIL_INDEX_V(p_pos, size() + 1, ERR_INVALID_PARAMETER);
resize(size() + 1);
for (int i = (size() - 1); i > p_pos; i--) {
set(i, get(i - 1));
int new_size = size() + 1;
ERR_FAIL_INDEX_V(p_pos, new_size, ERR_INVALID_PARAMETER);
Error err = resize(new_size);
ERR_FAIL_COND_V(err, err);
T *p = ptrw();
for (int i = new_size - 1; i > p_pos; i--) {
p[i] = std::move(p[i - 1]);
}
set(p_pos, p_val);
p[p_pos] = p_val;
return OK;
};
}
int find(const T &p_val, int p_from = 0) const;
_FORCE_INLINE_ CowData();
_FORCE_INLINE_ ~CowData();
_FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); };
_FORCE_INLINE_ CowData(CowData<T> &p_from) { _ref(p_from); }
};
template <class T>

View file

@ -444,6 +444,16 @@ public:
}
}
void operator=(List &&p_list) {
if (unlikely(this == &p_list)) {
return;
}
clear();
_data = p_list._data;
p_list._data = nullptr;
}
T &operator[](int p_index) {
CRASH_BAD_INDEX(p_index, size());
@ -685,6 +695,11 @@ public:
}
}
List(List &&p_list) {
_data = p_list._data;
p_list._data = nullptr;
}
List() {
_data = nullptr;
};

View file

@ -38,6 +38,7 @@
#include "core/vector.h"
#include <type_traits>
#include <utility>
template <class T, class U = uint32_t, bool force_trivial = false>
class LocalVector {
@ -67,9 +68,9 @@ public:
}
if (!std::is_trivially_constructible<T>::value && !force_trivial) {
memnew_placement(&data[count++], T(p_elem));
memnew_placement(&data[count++], T(std::move(p_elem)));
} else {
data[count++] = p_elem;
data[count++] = std::move(p_elem);
}
}
@ -77,7 +78,7 @@ public:
ERR_FAIL_UNSIGNED_INDEX(p_index, count);
count--;
for (U i = p_index; i < count; i++) {
data[i] = data[i + 1];
data[i] = std::move(data[i + 1]);
}
if (!std::is_trivially_destructible<T>::value && !force_trivial) {
data[count].~T();
@ -90,7 +91,7 @@ public:
ERR_FAIL_INDEX(p_index, count);
count--;
if (count > p_index) {
data[p_index] = data[count];
data[p_index] = std::move(data[count]);
}
if (!std::is_trivially_destructible<T>::value && !force_trivial) {
data[count].~T();
@ -193,13 +194,13 @@ public:
void insert(U p_pos, T p_val) {
ERR_FAIL_UNSIGNED_INDEX(p_pos, count + 1);
if (p_pos == count) {
push_back(p_val);
push_back(std::move(p_val));
} else {
resize(count + 1);
for (U i = count - 1; i > p_pos; i--) {
data[i] = data[i - 1];
data[i] = std::move(data[i - 1]);
}
data[p_pos] = p_val;
data[p_pos] = std::move(p_val);
}
}
@ -284,6 +285,17 @@ public:
data[i] = r[i];
}
}
LocalVector(LocalVector &&p_from) {
data = p_from.data;
count = p_from.count;
capacity = p_from.capacity;
p_from.data = nullptr;
p_from.count = 0;
p_from.capacity = 0;
}
inline LocalVector &operator=(const LocalVector &p_from) {
resize(p_from.size());
for (U i = 0; i < p_from.count; i++) {
@ -291,6 +303,22 @@ public:
}
return *this;
}
inline void operator=(LocalVector &&p_from) {
if (unlikely(this == &p_from)) {
return;
}
reset();
data = p_from.data;
count = p_from.count;
capacity = p_from.capacity;
p_from.data = nullptr;
p_from.count = 0;
p_from.capacity = 0;
}
inline LocalVector &operator=(const Vector<T> &p_from) {
resize(p_from.size());
for (U i = 0; i < count; i++) {
@ -298,6 +326,14 @@ public:
}
return *this;
}
inline void operator=(Vector<T> &&p_from) {
resize(p_from.size());
for (U i = 0; i < count; i++) {
data[i] = std::move(p_from[i]);
}
}
inline LocalVector &operator=(const PoolVector<T> &p_from) {
resize(p_from.size());
typename PoolVector<T>::Read r = p_from.read();

View file

@ -163,6 +163,23 @@ public:
};
void operator=(const StringName &p_name);
StringName &operator=(StringName &&p_name) {
if (_data == p_name._data) {
return *this;
}
unref();
_data = p_name._data;
p_name._data = nullptr;
return *this;
}
StringName(StringName &&p_name) {
_data = p_name._data;
p_name._data = nullptr;
}
StringName(const char *p_name);
StringName(const StringName &p_name);
StringName(const String &p_name);

View file

@ -32,6 +32,7 @@
#define TYPEDEFS_H
#include <stddef.h>
#include <utility>
/**
* Basic definitions and simple functions to be used everywhere.
@ -175,15 +176,7 @@ T *_nullptr() {
/** Generic swap template */
#ifndef SWAP
#define SWAP(m_x, m_y) __swap_tmpl((m_x), (m_y))
template <class T>
inline void __swap_tmpl(T &x, T &y) {
T aux = x;
x = y;
y = aux;
}
#define SWAP(m_x, m_y) std::swap((m_x), (m_y))
#endif //swap
/* clang-format off */

View file

@ -159,7 +159,7 @@ private:
Basis *_basis;
Transform *_transform;
void *_ptr; //generic pointer
uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)];
uint8_t _mem[sizeof(ObjData) > (sizeof(real_t) * 4) ? sizeof(ObjData) : (sizeof(real_t) * 4)]{ 0 };
} _data GCC_ALIGNED_8;
void reference(const Variant &p_variant);
@ -432,7 +432,21 @@ public:
static void construct_from_string(const String &p_string, Variant &r_value, ObjectConstruct p_obj_construct = nullptr, void *p_construct_ud = nullptr);
void operator=(const Variant &p_variant); // only this is enough for all the other types
void operator=(Variant &&p_variant) {
if (unlikely(this == &p_variant)) {
return;
}
clear();
type = p_variant.type;
_data = p_variant._data;
p_variant.type = NIL;
}
Variant(const Variant &p_variant);
Variant(Variant &&p_variant) {
type = p_variant.type;
_data = p_variant._data;
p_variant.type = NIL;
}
_FORCE_INLINE_ Variant() { type = NIL; }
_FORCE_INLINE_ ~Variant() {
if (type != Variant::NIL) {