any: self assignment

This commit is contained in:
skypjack
2024-07-17 16:10:58 +02:00
parent f104c5de99
commit 7e9b27f9c1
2 changed files with 70 additions and 4 deletions

View File

@@ -225,10 +225,12 @@ public:
* @return This any object.
*/
basic_any &operator=(const basic_any &other) {
reset();
if(this != &other) {
reset();
if(other.vtable) {
other.vtable(operation::copy, other, this);
if(other.vtable) {
other.vtable(operation::copy, other, this);
}
}
return *this;
@@ -240,6 +242,8 @@ public:
* @return This any object.
*/
basic_any &operator=(basic_any &&other) noexcept {
ENTT_ASSERT(this != &other, "Self move assignment");
reset();
if(other.vtable) {

View File

@@ -193,6 +193,19 @@ TEST(Any, SBOCopyAssignment) {
ASSERT_EQ(entt::any_cast<int>(other), 2);
}
TEST(Any, SBOSelfCopyAssignment) {
entt::any any{2};
// avoid warnings due to self-assignment
any = *&any;
ASSERT_TRUE(any);
ASSERT_EQ(any.policy(), entt::any_policy::owner);
ASSERT_EQ(any.type(), entt::type_id<int>());
ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
ASSERT_EQ(entt::any_cast<int>(any), 2);
}
TEST(Any, SBOMoveConstruction) {
entt::any any{2};
entt::any other{std::move(any)};
@@ -222,6 +235,13 @@ TEST(Any, SBOMoveAssignment) {
ASSERT_EQ(entt::any_cast<int>(other), 2);
}
ENTT_DEBUG_TEST(AnyDeathTest, SBOSelfMoveAssignment) {
entt::any any{2};
// avoid warnings due to self-assignment
ASSERT_DEATH(any = std::move(*&any), "");
}
TEST(Any, SBODirectAssignment) {
entt::any any{};
any = 2;
@@ -444,6 +464,20 @@ TEST(Any, NoSBOCopyAssignment) {
ASSERT_EQ(entt::any_cast<fat>(other), instance);
}
TEST(Any, NoSBOSelfCopyAssignment) {
const fat instance{.1, .2, .3, .4};
entt::any any{instance};
// avoid warnings due to self-assignment
any = *&any;
ASSERT_TRUE(any);
ASSERT_EQ(any.policy(), entt::any_policy::owner);
ASSERT_EQ(any.type(), entt::type_id<fat>());
ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
ASSERT_EQ(entt::any_cast<fat>(any), instance);
}
TEST(Any, NoSBOMoveConstruction) {
const fat instance{.1, .2, .3, .4};
entt::any any{instance};
@@ -475,6 +509,14 @@ TEST(Any, NoSBOMoveAssignment) {
ASSERT_EQ(entt::any_cast<fat>(other), instance);
}
ENTT_DEBUG_TEST(AnyDeathTest, NoSBOSelfMoveAssignment) {
const fat instance{.1, .2, .3, .4};
entt::any any{instance};
// avoid warnings due to self-assignment
ASSERT_DEATH(any = std::move(*&any), "");
}
TEST(Any, NoSBODirectAssignment) {
const fat instance{.1, .2, .3, .4};
entt::any any{};
@@ -615,7 +657,7 @@ TEST(Any, VoidCopyConstruction) {
}
TEST(Any, VoidCopyAssignment) {
entt::any any{std::in_place_type<void>};
const entt::any any{std::in_place_type<void>};
entt::any other{2};
other = any;
@@ -628,6 +670,19 @@ TEST(Any, VoidCopyAssignment) {
ASSERT_EQ(entt::any_cast<double>(&other), nullptr);
}
TEST(Any, VoidSelfCopyAssignment) {
entt::any any{std::in_place_type<void>};
// avoid warnings due to self-assignment
any = *&any;
ASSERT_FALSE(any);
ASSERT_EQ(any.policy(), entt::any_policy::owner);
ASSERT_EQ(any.type(), entt::type_id<void>());
ASSERT_EQ(entt::any_cast<int>(&any), nullptr);
ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
}
TEST(Any, VoidMoveConstruction) {
entt::any any{std::in_place_type<void>};
entt::any other{std::move(any)};
@@ -655,6 +710,13 @@ TEST(Any, VoidMoveAssignment) {
ASSERT_EQ(entt::any_cast<double>(&other), nullptr);
}
ENTT_DEBUG_TEST(AnyDeathTest, VoidSelfMoveAssignment) {
entt::any any{std::in_place_type<void>};
// avoid warnings due to self-assignment
ASSERT_DEATH(any = std::move(*&any), "");
}
TEST(Any, SBOMoveValidButUnspecifiedState) {
entt::any any{2};
entt::any other{std::move(any)};