Implement copy move & assign for buffer
This commit is contained in:
@ -5,6 +5,7 @@
|
||||
#include "asl/annotations.hpp"
|
||||
#include "asl/memory.hpp"
|
||||
#include "asl/assert.hpp"
|
||||
#include "asl/span.hpp"
|
||||
|
||||
namespace asl
|
||||
{
|
||||
@ -141,7 +142,7 @@ private:
|
||||
isize_t other_n = other.size();
|
||||
isize_t this_n = size();
|
||||
resize_uninit(other_n);
|
||||
if (other_n < this_n)
|
||||
if (other_n <= this_n)
|
||||
{
|
||||
relocate_assign_n(data(), other.data(), other_n);
|
||||
}
|
||||
@ -168,6 +169,26 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void copy_range(span<const T> to_copy)
|
||||
{
|
||||
isize_t this_size = size();
|
||||
isize_t new_size = to_copy.size();
|
||||
|
||||
resize_uninit(to_copy.size());
|
||||
ASL_ASSERT(capacity() >= new_size);
|
||||
ASL_ASSERT(size() == to_copy.size());
|
||||
|
||||
if (new_size <= this_size)
|
||||
{
|
||||
copy_assign_n(data(), to_copy.data(), new_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_assign_n(data(), to_copy.data(), this_size);
|
||||
copy_uninit_n(data() + this_size, to_copy.data() + this_size, new_size - this_size);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr buffer() requires default_constructible<Allocator> = default;
|
||||
|
||||
@ -175,13 +196,30 @@ public:
|
||||
: m_allocator{ASL_MOVE(allocator)}
|
||||
{}
|
||||
|
||||
constexpr buffer(const buffer& other)
|
||||
requires copy_constructible<Allocator> && copyable<T>
|
||||
: m_allocator{other.m_allocator}
|
||||
{
|
||||
copy_range(other);
|
||||
}
|
||||
|
||||
constexpr buffer(buffer&& other)
|
||||
requires moveable<T>
|
||||
: buffer(ASL_MOVE(other.m_allocator))
|
||||
{
|
||||
move_from_other(ASL_MOVE(other), false);
|
||||
}
|
||||
|
||||
constexpr buffer& operator=(const buffer& other)
|
||||
requires copyable<T>
|
||||
{
|
||||
if (&other == this) { return *this; }
|
||||
copy_range(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr buffer& operator=(buffer&& other)
|
||||
requires moveable<T>
|
||||
{
|
||||
if (&other == this) { return *this; }
|
||||
move_from_other(ASL_MOVE(other), true);
|
||||
@ -193,8 +231,6 @@ public:
|
||||
destroy();
|
||||
}
|
||||
|
||||
// @Todo Copy constructor & assignment
|
||||
|
||||
constexpr isize_t size() const
|
||||
{
|
||||
return decode_size(load_size_encoded());
|
||||
@ -307,6 +343,17 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// @Todo(C++23) Deducing this
|
||||
operator span<const T>() const // NOLINT(*-explicit-conversions)
|
||||
{
|
||||
return span<const T>{data(), size()};
|
||||
}
|
||||
|
||||
operator span<T>() // NOLINT(*-explicit-conversions)
|
||||
{
|
||||
return span<T>{data(), size()};
|
||||
}
|
||||
|
||||
// @Todo(C++23) Use deducing this
|
||||
constexpr T& operator[](isize_t i)
|
||||
{
|
||||
|
@ -56,6 +56,40 @@ constexpr void destroy_n(T* data, isize_t n)
|
||||
}
|
||||
}
|
||||
|
||||
template<copy_constructible T>
|
||||
constexpr void copy_uninit_n(T* to, const T* from, isize_t n)
|
||||
{
|
||||
if constexpr (trivially_copy_constructible<T>)
|
||||
{
|
||||
memcpy(to, from, size_of<T> * n);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (isize_t i = 0; i < n; ++i)
|
||||
{
|
||||
// NOLINTNEXTLINE(*-pointer-arithmetic)
|
||||
construct_at<T>(to + i, from[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<copy_assignable T>
|
||||
constexpr void copy_assign_n(T* to, const T* from, isize_t n)
|
||||
{
|
||||
if constexpr (trivially_copy_constructible<T>)
|
||||
{
|
||||
memcpy(to, from, size_of<T> * n);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (isize_t i = 0; i < n; ++i)
|
||||
{
|
||||
// NOLINTNEXTLINE(*-pointer-arithmetic)
|
||||
to[i] = from[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<move_constructible T>
|
||||
constexpr void relocate_uninit_n(T* to, T* from, isize_t n)
|
||||
{
|
||||
|
@ -469,3 +469,64 @@ ASL_TEST(move_assign_from_inline_incompatible_allocator)
|
||||
ASL_TEST_EXPECT(d[4] == true);
|
||||
ASL_TEST_EXPECT(d[5] == true);
|
||||
}
|
||||
|
||||
ASL_TEST(copy_construct_inline)
|
||||
{
|
||||
asl::buffer<int> buf;
|
||||
buf.push(0);
|
||||
buf.push(1);
|
||||
buf.push(2);
|
||||
|
||||
asl::buffer<int> buf2{buf};
|
||||
|
||||
ASL_TEST_EXPECT(buf.size() == buf2.size());
|
||||
ASL_TEST_EXPECT(buf.size() == 3);
|
||||
ASL_TEST_EXPECT(buf[0] == 0);
|
||||
ASL_TEST_EXPECT(buf[1] == 1);
|
||||
ASL_TEST_EXPECT(buf[2] == 2);
|
||||
ASL_TEST_EXPECT(buf2[0] == 0);
|
||||
ASL_TEST_EXPECT(buf2[1] == 1);
|
||||
ASL_TEST_EXPECT(buf2[2] == 2);
|
||||
}
|
||||
|
||||
ASL_TEST(copy_assign_into_smaller)
|
||||
{
|
||||
asl::buffer<int> buf;
|
||||
buf.push(0);
|
||||
buf.push(1);
|
||||
buf.push(2);
|
||||
|
||||
asl::buffer<int> buf2;
|
||||
buf2.push(4);
|
||||
|
||||
buf2 = buf;
|
||||
|
||||
ASL_TEST_EXPECT(buf.size() == 3);
|
||||
ASL_TEST_EXPECT(buf2.size() == 3);
|
||||
|
||||
ASL_TEST_EXPECT(buf[0] == 0);
|
||||
ASL_TEST_EXPECT(buf[1] == 1);
|
||||
ASL_TEST_EXPECT(buf[2] == 2);
|
||||
ASL_TEST_EXPECT(buf2[0] == 0);
|
||||
ASL_TEST_EXPECT(buf2[1] == 1);
|
||||
ASL_TEST_EXPECT(buf2[2] == 2);
|
||||
}
|
||||
|
||||
ASL_TEST(copy_assign_into_larger)
|
||||
{
|
||||
asl::buffer<int> buf;
|
||||
buf.push(0);
|
||||
buf.push(1);
|
||||
buf.push(2);
|
||||
|
||||
asl::buffer<int> buf2;
|
||||
buf2.push(4);
|
||||
|
||||
buf = buf2;
|
||||
|
||||
ASL_TEST_EXPECT(buf.size() == 1);
|
||||
ASL_TEST_EXPECT(buf2.size() == 1);
|
||||
|
||||
ASL_TEST_EXPECT(buf[0] == 4);
|
||||
ASL_TEST_EXPECT(buf2[0] == 4);
|
||||
}
|
||||
|
Reference in New Issue
Block a user