mirror of
https://github.com/SerenityOS/serenity
synced 2026-04-25 17:15:42 +02:00
AK: Dont trivially move Optional<T> when T is not trivially destructible
This mirrors what `std::optional` is doing. Co-Authored-By: Dan Klishch <danilklishch@gmail.com>
This commit is contained in:
committed by
Andrew Kaster
parent
3264385dc9
commit
f2f18d9025
@@ -135,7 +135,9 @@ public:
|
||||
requires(!IsMoveConstructible<T> || !IsDestructible<T>)
|
||||
= delete;
|
||||
ALWAYS_INLINE constexpr Optional& operator=(Optional&& other)
|
||||
requires(IsMoveAssignable<T> && IsMoveConstructible<T> && !IsTriviallyMoveAssignable<T>)
|
||||
requires(
|
||||
IsMoveAssignable<T> && IsMoveConstructible<T>
|
||||
&& (!IsTriviallyMoveAssignable<T> || !IsTriviallyMoveConstructible<T> || !IsTriviallyDestructible<T>))
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
@@ -153,7 +155,9 @@ public:
|
||||
}
|
||||
|
||||
ALWAYS_INLINE constexpr Optional& operator=(Optional&& other)
|
||||
requires(IsMoveConstructible<T> && !IsMoveAssignable<T>)
|
||||
requires(
|
||||
IsMoveConstructible<T> && !IsMoveAssignable<T>
|
||||
&& (!IsTriviallyMoveConstructible<T> || !IsTriviallyDestructible<T>))
|
||||
{
|
||||
clear();
|
||||
|
||||
|
||||
@@ -332,6 +332,33 @@ TEST_CASE(uninitialized_constructor)
|
||||
EXPECT(!opt.value().m_default_constructed);
|
||||
}
|
||||
|
||||
TEST_CASE(non_trivial_destructor_is_called_on_move_assignment)
|
||||
{
|
||||
static int foo_destruction_count = 0;
|
||||
|
||||
struct Foo {
|
||||
Foo() { }
|
||||
Foo(Foo&&) = default;
|
||||
~Foo()
|
||||
{
|
||||
++foo_destruction_count;
|
||||
}
|
||||
|
||||
Foo& operator=(Foo&&) = default;
|
||||
};
|
||||
static_assert(!IsTriviallyMoveAssignable<Optional<Foo>>);
|
||||
|
||||
Optional<Foo> foo = Foo {}; // 1. The immediate value needs to be destroyed
|
||||
Optional<Foo> foo2;
|
||||
foo = AK::move(foo2); // 2. The move releases the value, which destroys the moved-from stored value
|
||||
|
||||
EXPECT_EQ(foo_destruction_count, 2);
|
||||
|
||||
// As Optional<Foo> does not trivially move, moved-from values are empty
|
||||
// Ignoring the fact that we are touching a moved from value here
|
||||
EXPECT_EQ(foo.has_value(), false);
|
||||
}
|
||||
|
||||
consteval bool test_constexpr()
|
||||
{
|
||||
Optional<int> none;
|
||||
|
||||
Reference in New Issue
Block a user