Browse Source

meta: avoid overwriting traits/custom data on rebind

Michele Caini 1 year ago
parent
commit
1beac44dda
5 changed files with 32 additions and 5 deletions
  1. 1 0
      TODO
  2. 5 5
      src/entt/meta/factory.hpp
  3. 10 0
      test/entt/meta/meta_data.cpp
  4. 7 0
      test/entt/meta/meta_func.cpp
  5. 9 0
      test/entt/meta/meta_type.cpp

+ 1 - 0
TODO

@@ -45,3 +45,4 @@ TODO:
 * natvis for meta_custom
 * meta: vectors for details and props
 * suppress -Wself-move on CI with g++13
+* meta_custom operator bool

+ 5 - 5
src/entt/meta/factory.hpp

@@ -74,7 +74,10 @@ protected:
     }
 
     void data(const id_type id, meta_data_node node) {
-        details->data.insert_or_assign(id, std::move(node));
+        if(auto it = details->data.find(id); it == details->data.end() || it->second.set != node.set || it->second.get != node.get) {
+            details->data.insert_or_assign(id, std::move(node));
+        }
+
         invoke = nullptr;
         bucket = id;
     }
@@ -93,12 +96,9 @@ protected:
 
             if(curr->invoke != node.invoke) {
                 curr->next = std::make_shared<meta_func_node>();
-                curr = curr->next.get();
+                *curr->next = std::move(node);
             }
 
-            node.next = std::move(curr->next);
-            *curr = std::move(node);
-
             invoke = curr->invoke;
             bucket = id;
         }

+ 10 - 0
test/entt/meta/meta_data.cpp

@@ -702,6 +702,16 @@ TEST_F(MetaData, ReRegistration) {
     ASSERT_EQ(node.details->data.size(), 2u);
     ASSERT_TRUE(type.data("value"_hs));
     ASSERT_TRUE(type.data("field"_hs));
+
+    entt::meta<base>()
+        .data<&base::value>("field"_hs)
+        .traits(test::meta_traits::one)
+        .custom<int>(3)
+        // this should not overwrite traits and custom data
+        .data<&base::value>("field"_hs);
+
+    ASSERT_EQ(type.data("field"_hs).traits<test::meta_traits>(), test::meta_traits::one);
+    ASSERT_NE(static_cast<const int *>(type.data("field"_hs).custom()), nullptr);
 }
 
 TEST_F(MetaData, CollisionAndReuse) {

+ 7 - 0
test/entt/meta/meta_func.cpp

@@ -665,6 +665,10 @@ TEST_F(MetaFunc, ReRegistration) {
     ASSERT_FALSE(type.invoke("f1"_hs, instance, 0, 0));
 
     entt::meta<function>()
+        .func<entt::overload<int(int, int)>(&function::f)>("f"_hs)
+        .traits(test::meta_traits::one)
+        .custom<int>(3)
+        // this should not overwrite traits and custom data
         .func<entt::overload<int(int, int)>(&function::f)>("f"_hs)
         .func<entt::overload<int(int) const>(&function::f)>("f"_hs);
 
@@ -675,5 +679,8 @@ TEST_F(MetaFunc, ReRegistration) {
     ASSERT_TRUE(type.invoke("f"_hs, instance, 0));
     ASSERT_TRUE(type.invoke("f"_hs, instance, 0, 0));
 
+    ASSERT_EQ(type.func("f"_hs).traits<test::meta_traits>(), test::meta_traits::one);
+    ASSERT_NE(static_cast<const int *>(type.func("f"_hs).custom()), nullptr);
+
     ASSERT_EQ(reset_and_check(), 0u);
 }

+ 9 - 0
test/entt/meta/meta_type.cpp

@@ -830,11 +830,20 @@ TEST_F(MetaType, ReRegistration) {
     ASSERT_EQ(count, 0);
     ASSERT_TRUE(entt::resolve("double"_hs));
 
+    entt::meta<double>()
+        .type("real"_hs)
+        .traits(test::meta_traits::one)
+        .custom<int>(3);
+
+    // this should not overwrite traits and custom data
     entt::meta<double>().type("real"_hs);
 
     ASSERT_FALSE(entt::resolve("double"_hs));
     ASSERT_TRUE(entt::resolve("real"_hs));
     ASSERT_TRUE(entt::resolve("real"_hs).data("var"_hs));
+
+    ASSERT_EQ(entt::resolve<double>().traits<test::meta_traits>(), test::meta_traits::one);
+    ASSERT_NE(static_cast<const int *>(entt::resolve<double>().custom()), nullptr);
 }
 
 TEST_F(MetaType, NameCollision) {