AK: Teach Vector::insert() to use memmove() for trivial types

This commit is contained in:
Andreas Kling 2020-01-19 12:15:43 +01:00
parent 109727082c
commit 502626eecb
Notes: sideshowbarker 2024-07-19 09:57:39 +09:00
2 changed files with 32 additions and 3 deletions

View file

@ -295,4 +295,22 @@ TEST_CASE(nonnullownptrvector)
EXPECT_EQ(objects.size(), 2);
}
TEST_CASE(insert_trivial)
{
Vector<int> ints;
ints.append(0);
ints.append(10);
ints.append(20);
ints.append(30);
ints.append(40);
ints.insert(2, 15);
EXPECT_EQ(ints.size(), 6);
EXPECT_EQ(ints[0], 0);
EXPECT_EQ(ints[1], 10);
EXPECT_EQ(ints[2], 15);
EXPECT_EQ(ints[3], 20);
EXPECT_EQ(ints[4], 30);
EXPECT_EQ(ints[5], 40);
}
TEST_MAIN(Vector)

View file

@ -94,6 +94,8 @@ class TypedTransfer {
public:
static void move(T* destination, T* source, size_t count)
{
if (!count)
return;
if constexpr (Traits<T>::is_trivial()) {
memmove(destination, source, count * sizeof(T));
return;
@ -104,6 +106,8 @@ public:
static void copy(T* destination, const T* source, size_t count)
{
if (!count)
return;
if constexpr (Traits<T>::is_trivial()) {
memmove(destination, source, count * sizeof(T));
return;
@ -114,6 +118,9 @@ public:
static bool compare(const T* a, const T* b, size_t count)
{
if (!count)
return true;
if constexpr (Traits<T>::is_trivial())
return !memcmp(a, b, count * sizeof(T));
@ -335,9 +342,13 @@ public:
return append(move(value));
grow_capacity(size() + 1);
++m_size;
for (int i = size() - 1; i > index; --i) {
new (slot(i)) T(move(at(i - 1)));
at(i - 1).~T();
if constexpr (Traits<T>::is_trivial()) {
TypedTransfer<T>::move(slot(index + 1), slot(index), m_size - index - 1);
} else {
for (int i = size() - 1; i > index; --i) {
new (slot(i)) T(move(at(i - 1)));
at(i - 1).~T();
}
}
new (slot(index)) T(move(value));
}