skypjack пре 1 година
родитељ
комит
7e9b27f9c1
2 измењених фајлова са 70 додато и 4 уклоњено
  1. 7 3
      src/entt/core/any.hpp
  2. 63 1
      test/entt/core/any.cpp

+ 7 - 3
src/entt/core/any.hpp

@@ -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) {

+ 63 - 1
test/entt/core/any.cpp

@@ -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)};