Просмотр исходного кода

meta: invalid meta_any when copying non-copyable types

skypjack 3 недель назад
Родитель
Сommit
0bb54130c9
3 измененных файлов с 30 добавлено и 5 удалено
  1. 0 1
      TODO
  2. 9 4
      src/entt/meta/meta.hpp
  3. 21 0
      test/entt/meta/meta_any.cpp

+ 0 - 1
TODO

@@ -35,4 +35,3 @@ TODO:
 * introduce a way to inject stl from outside too
 * introduce a way to inject stl from outside too
 * export optional as meta_pointer like (or refine meta-pointer like detection)
 * export optional as meta_pointer like (or refine meta-pointer like detection)
 * redesign snapshot as a whole
 * redesign snapshot as a whole
-* meta_any::operator bool() for non-copyable types should return false after a copy

+ 9 - 4
src/entt/meta/meta.hpp

@@ -335,7 +335,12 @@ public:
      * @brief Copy constructor.
      * @brief Copy constructor.
      * @param other The instance to copy from.
      * @param other The instance to copy from.
      */
      */
-    meta_any(const meta_any &other) = default;
+    meta_any(const meta_any &other)
+        : storage{other.storage},
+          ctx{other.ctx},
+          node{(other.storage && !storage) ? nullptr : other.node},
+          vtable{(other.storage && !storage) ? nullptr : other.vtable} {
+    }
 
 
     /**
     /**
      * @brief Move constructor.
      * @brief Move constructor.
@@ -357,10 +362,10 @@ public:
      */
      */
     meta_any &operator=(const meta_any &other) {
     meta_any &operator=(const meta_any &other) {
         if(this != &other) {
         if(this != &other) {
-            storage = other.storage;
             ctx = other.ctx;
             ctx = other.ctx;
-            node = other.node;
-            vtable = other.vtable;
+            storage = other.storage;
+            node = (other.storage && !storage) ? nullptr : other.node;
+            vtable = (other.storage && !storage) ? nullptr : other.vtable;
         }
         }
 
 
         return *this;
         return *this;

+ 21 - 0
test/entt/meta/meta_any.cpp

@@ -1601,3 +1601,24 @@ TEST_F(MetaAny, ForwardAsMeta) {
     ASSERT_NE(any.base().data(), &value);
     ASSERT_NE(any.base().data(), &value);
     ASSERT_EQ(ref.base().data(), &value);
     ASSERT_EQ(ref.base().data(), &value);
 }
 }
+
+TEST_F(MetaAny, NonCopyableType) {
+    const std::unique_ptr<int> value{};
+    entt::meta_any any{std::in_place_type<std::unique_ptr<int>>};
+    entt::meta_any other = entt::forward_as_meta(value);
+
+    ASSERT_TRUE(any);
+    ASSERT_TRUE(other);
+
+    ASSERT_FALSE(any.assign(std::move(other)));
+
+    entt::meta_any copy{any};
+
+    ASSERT_TRUE(any);
+    ASSERT_FALSE(copy);
+
+    copy = any;
+
+    ASSERT_TRUE(any);
+    ASSERT_FALSE(copy);
+}