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

meta: safer factory, no-op re-registration

Michele Caini 5 лет назад
Родитель
Сommit
1512fbae55

+ 0 - 1
TODO

@@ -15,7 +15,6 @@ WIP:
 * HP: review registry::get, registry::try_get
 * HP: weak reference wrapper example with custom storage
 * HP: merge view and view pack
-* HP: invalid view auto-refresh
 * HP: paginate pools
 * HP: headless (sparse set only) view
 * HP: write documentation for custom storages and views!!

+ 20 - 24
src/entt/meta/factory.hpp

@@ -91,9 +91,10 @@ class meta_factory<Type, Spec...>: public meta_factory<Type> {
             }
         };
 
-        ENTT_ASSERT(!exists(node.key(), *curr));
-        node.next = *curr;
-        *curr = &node;
+        if(!exists(node.key(), *curr)) {
+            node.next = *curr;
+            *curr = &node;
+        }
     }
 
 public:
@@ -160,8 +161,8 @@ class meta_factory<Type> {
     }
 
     template<typename Node>
-    Node * find(const id_type id, Node *node) ENTT_NOEXCEPT {
-        return (!node || node->id == id) ? node : find(id, node->next);
+    Node * find(const id_type id, Node *node, const Node *owner) ENTT_NOEXCEPT {
+        return (!node || (node->id == id && node != owner)) ? node : find(id, node->next, owner);
     }
 
 public:
@@ -173,10 +174,9 @@ public:
     auto type(const id_type id = type_hash<Type>::value()) {
         auto * const node = internal::meta_info<Type>::resolve();
 
-        ENTT_ASSERT(!find(id, *internal::meta_context::global()));
-        node->id = id;
-
         if(!exists(node, *internal::meta_context::global())) {
+            ENTT_ASSERT(!find(id, *internal::meta_context::global(), node));
+            node->id = id;
             node->next = *internal::meta_context::global();
             *internal::meta_context::global() = node;
         }
@@ -376,8 +376,6 @@ public:
         static_assert(std::is_invocable_v<decltype(Func), Type &>, "The function doesn't accept an object of the type provided");
         auto * const type = internal::meta_info<Type>::resolve();
 
-        ENTT_ASSERT(!type->dtor);
-
         type->dtor = [](void *instance) {
             if(instance) {
                 std::invoke(Func, *static_cast<Type *>(instance));
@@ -420,10 +418,9 @@ public:
                 &meta_getter<Type, Data, Policy>
             };
 
-            ENTT_ASSERT(!find(id, type->data));
-            node.id = id;
-
             if(!exists(&node, type->data)) {
+                ENTT_ASSERT(!find(id, type->data, &node));
+                node.id = id;
                 node.next = type->data;
                 type->data = &node;
             }
@@ -469,10 +466,9 @@ public:
             &meta_getter<Type, Getter, Policy>
         };
 
-        ENTT_ASSERT(!find(id, type->data));
-        node.id = id;
-
         if(!exists(&node, type->data)) {
+            ENTT_ASSERT(!find(id, type->data, &node));
+            node.id = id;
             node.next = type->data;
             type->data = &node;
         }
@@ -515,15 +511,15 @@ public:
             }
         };
 
-        ENTT_ASSERT(!exists(&node, type->func));
-
-        internal::meta_func_node **it = &type->func;
-        for(; *it && (*it)->id != id; it = &(*it)->next);
-        for(; *it && (*it)->id == id && (*it)->arity < node.arity; it = &(*it)->next);
+        if(!exists(&node, type->func)) {
+            internal::meta_func_node **it = &type->func;
+            for(; *it && (*it)->id != id; it = &(*it)->next);
+            for(; *it && (*it)->id == id && (*it)->arity < node.arity; it = &(*it)->next);
 
-        node.id = id;
-        node.next = *it;
-        *it = &node;
+            node.id = id;
+            node.next = *it;
+            *it = &node;
+        }
 
         return meta_factory<Type, std::integral_constant<decltype(Candidate), Candidate>>{&node.prop};
     }

+ 3 - 0
test/CMakeLists.txt

@@ -188,9 +188,12 @@ SETUP_BASIC_TEST(locator entt/locator/locator.cpp)
 # Test meta
 
 SETUP_BASIC_TEST(meta_any entt/meta/meta_any.cpp)
+SETUP_BASIC_TEST(meta_base entt/meta/meta_base.cpp)
 SETUP_BASIC_TEST(meta_container entt/meta/meta_container.cpp)
+SETUP_BASIC_TEST(meta_conv entt/meta/meta_conv.cpp)
 SETUP_BASIC_TEST(meta_ctor entt/meta/meta_ctor.cpp)
 SETUP_BASIC_TEST(meta_data entt/meta/meta_data.cpp)
+SETUP_BASIC_TEST(meta_dtor entt/meta/meta_dtor.cpp)
 SETUP_BASIC_TEST(meta_func entt/meta/meta_func.cpp)
 SETUP_BASIC_TEST(meta_handle entt/meta/meta_handle.cpp)
 SETUP_BASIC_TEST(meta_pointer entt/meta/meta_pointer.cpp)

+ 19 - 6
test/entt/meta/meta_any.cpp

@@ -52,23 +52,36 @@ struct unmanageable_t {
 };
 
 struct MetaAny: ::testing::Test {
-    static void SetUpTestCase() {
+    void SetUp() override {
         using namespace entt::literals;
 
-        entt::meta<double>().conv<int>();
-        entt::meta<empty_t>().dtor<&empty_t::destroy>();
-        entt::meta<fat_t>().base<empty_t>().dtor<&fat_t::destroy>();
+        entt::meta<double>()
+            .type("double"_hs)
+            .conv<int>();
+
+        entt::meta<empty_t>()
+            .type("empty"_hs)
+            .dtor<&empty_t::destroy>();
+
+        entt::meta<fat_t>()
+            .type("fat"_hs)
+            .base<empty_t>()
+            .dtor<&fat_t::destroy>();
 
         entt::meta<clazz_t>()
             .type("clazz"_hs)
             .data<&clazz_t::value>("value"_hs)
             .func<&clazz_t::member>("member"_hs)
             .func<&clazz_t::func>("func"_hs);
-    }
 
-    void SetUp() override {
         empty_t::counter = 0;
     }
+
+    void TearDown() override {
+        for(auto type: entt::resolve()) {
+            type.reset();
+        }
+    }
 };
 
 TEST_F(MetaAny, SBO) {

+ 61 - 0
test/entt/meta/meta_base.cpp

@@ -0,0 +1,61 @@
+#include <gtest/gtest.h>
+#include <entt/meta/factory.hpp>
+#include <entt/meta/meta.hpp>
+#include <entt/meta/node.hpp>
+#include <entt/meta/resolve.hpp>
+
+struct base_t {
+    base_t() = default;
+    int value;
+};
+
+struct derived_t: base_t {
+    derived_t() = default;
+};
+
+struct MetaBase: ::testing::Test {
+    static void StaticSetUp() {
+        using namespace entt::literals;
+
+        entt::meta<derived_t>()
+            .type("derived"_hs)
+            .base<base_t>();
+    }
+
+    void SetUp() override {
+        StaticSetUp();
+    }
+
+    void TearDown() override {
+        for(auto type: entt::resolve()) {
+            type.reset();
+        }
+    }
+};
+
+TEST_F(MetaBase, Functionalities) {
+    auto any = entt::resolve<derived_t>().construct();
+    any.cast<derived_t &>().value = 42;
+    auto as_derived = any.as_ref();
+
+    ASSERT_TRUE(any.allow_cast<base_t &>());
+
+    ASSERT_FALSE(any.allow_cast<char>());
+    ASSERT_FALSE(as_derived.allow_cast<char>());
+
+    ASSERT_TRUE(any);
+    ASSERT_EQ(any.cast<base_t &>().value, as_derived.cast<derived_t &>().value);
+
+    any.cast<base_t &>().value = 3;
+
+    ASSERT_EQ(any.cast<const base_t &>().value, as_derived.cast<const derived_t &>().value);
+}
+
+TEST_F(MetaBase, ReRegistration) {
+    MetaBase::StaticSetUp();
+
+    auto *node = entt::internal::meta_info<derived_t>::resolve();
+
+    ASSERT_NE(node->base, nullptr);
+    ASSERT_EQ(node->base->next, nullptr);
+}

+ 16 - 3
test/entt/meta/meta_container.cpp

@@ -6,9 +6,22 @@
 #include <entt/meta/resolve.hpp>
 
 struct MetaContainer: ::testing::Test {
-    static void SetUpTestCase() {
-        entt::meta<double>().conv<int>();
-        entt::meta<int>().conv<char>();
+    void SetUp() override {
+        using namespace entt::literals;
+
+        entt::meta<double>()
+            .type("double"_hs)
+            .conv<int>();
+
+        entt::meta<int>()
+            .type("int"_hs)
+            .conv<char>();
+    }
+
+    void TearDown() override {
+        for(auto type: entt::resolve()) {
+            type.reset();
+        }
     }
 };
 

+ 63 - 0
test/entt/meta/meta_conv.cpp

@@ -0,0 +1,63 @@
+#include <utility>
+#include <gtest/gtest.h>
+#include <entt/meta/factory.hpp>
+#include <entt/meta/meta.hpp>
+#include <entt/meta/node.hpp>
+#include <entt/meta/resolve.hpp>
+
+struct clazz_t {
+    clazz_t() = default;
+    operator int() const { return value; }
+    int value;
+};
+
+double conv_to_double(const clazz_t &instance) {
+    return instance.value * 2.;
+}
+
+struct MetaConv: ::testing::Test {
+    static void StaticSetUp() {
+        using namespace entt::literals;
+
+        entt::meta<clazz_t>()
+            .type("clazz"_hs)
+            .conv<int>()
+            .conv<&conv_to_double>();
+    }
+
+    void SetUp() override {
+        StaticSetUp();
+    }
+
+    void TearDown() override {
+        for(auto type: entt::resolve()) {
+            type.reset();
+        }
+    }
+};
+
+TEST_F(MetaConv, Functionalities) {
+    auto any = entt::resolve<clazz_t>().construct();
+    any.cast<clazz_t &>().value = 42;
+
+    const auto as_int = std::as_const(any).allow_cast<int>();
+    const auto as_double = std::as_const(any).allow_cast<double>();
+
+    ASSERT_FALSE(any.allow_cast<char>());
+
+    ASSERT_TRUE(as_int);
+    ASSERT_TRUE(as_double);
+
+    ASSERT_EQ(as_int.cast<int>(), any.cast<clazz_t &>().value);
+    ASSERT_EQ(as_double.cast<double>(), conv_to_double(any.cast<clazz_t &>()));
+}
+
+TEST_F(MetaConv, ReRegistration) {
+    MetaConv::StaticSetUp();
+
+    auto *node = entt::internal::meta_info<clazz_t>::resolve();
+
+    ASSERT_NE(node->conv, nullptr);
+    ASSERT_NE(node->conv->next, nullptr);
+    ASSERT_EQ(node->conv->next->next, nullptr);
+}

+ 32 - 4
test/entt/meta/meta_ctor.cpp

@@ -33,19 +33,36 @@ struct clazz_t {
 double double_factory() { return 42.; }
 
 struct MetaCtor: ::testing::Test {
-    static void SetUpTestCase() {
+    static void StaticSetUp() {
         using namespace entt::literals;
 
-        entt::meta<double>().conv<int>().ctor<&double_factory>();
-        entt::meta<derived_t>().base<base_t>();
+        entt::meta<double>()
+            .type("double"_hs)
+            .conv<int>()
+            .ctor<&double_factory>();
 
-        entt::meta<clazz_t>().type("clazz"_hs)
+        entt::meta<derived_t>()
+            .type("derived"_hs)
+            .base<base_t>();
+
+        entt::meta<clazz_t>()
+            .type("clazz"_hs)
             .ctor<&entt::registry::emplace_or_replace<clazz_t, const int &, const char &>, entt::as_ref_t>()
             .ctor<const base_t &, int>()
             .ctor<const int &, char>().prop(3, false)
             .ctor<entt::overload<clazz_t(int)>(&clazz_t::factory)>().prop('c', 42)
             .ctor<entt::overload<clazz_t(base_t, int, int)>(&clazz_t::factory)>();
     }
+
+    void SetUp() override {
+        StaticSetUp();
+    }
+
+    void TearDown() override {
+        for(auto type: entt::resolve()) {
+            type.reset();
+        }
+    }
 };
 
 TEST_F(MetaCtor, Functionalities) {
@@ -262,3 +279,14 @@ TEST_F(MetaCtor, NonDefaultConstructibleType) {
     ASSERT_EQ(counter, 5);
     ASSERT_FALSE(type.ctor<>());
 }
+
+TEST_F(MetaCtor, ReRegistration) {
+    MetaCtor::StaticSetUp();
+
+    auto *node = entt::internal::meta_info<double>::resolve();
+
+    ASSERT_NE(node->ctor, nullptr);
+    // default constructor is implicitly generated
+    ASSERT_NE(node->ctor->next, nullptr);
+    ASSERT_EQ(node->ctor->next->next, nullptr);
+}

+ 34 - 6
test/entt/meta/meta_data.cpp

@@ -65,14 +65,25 @@ enum class property_t {
 };
 
 struct MetaData: ::testing::Test {
-    static void SetUpTestCase() {
+    static void StaticSetUp() {
         using namespace entt::literals;
 
-        entt::meta<double>().conv<int>();
-        entt::meta<base_t>().dtor<&base_t::destroy>().data<&base_t::value>("value"_hs);
-        entt::meta<derived_t>().base<base_t>().dtor<&derived_t::destroy>();
+        entt::meta<double>()
+            .type("double"_hs)
+            .conv<int>();
 
-        entt::meta<clazz_t>().type("clazz"_hs)
+        entt::meta<base_t>()
+            .type("base"_hs)
+            .dtor<&base_t::destroy>()
+            .data<&base_t::value>("value"_hs);
+
+        entt::meta<derived_t>()
+            .type("derived"_hs)
+            .base<base_t>()
+            .dtor<&derived_t::destroy>();
+
+        entt::meta<clazz_t>()
+            .type("clazz"_hs)
             .data<&clazz_t::i, entt::as_ref_t>("i"_hs).prop(3, 0)
             .data<&clazz_t::i, entt::as_cref_t>("ci"_hs)
             .data<&clazz_t::j>("j"_hs).prop(true, 1)
@@ -94,10 +105,18 @@ struct MetaData: ::testing::Test {
             .type("array"_hs)
             .data<&array_t::global>("global"_hs)
             .data<&array_t::local>("local"_hs);
+
+        base_t::counter = 0;
     }
 
     void SetUp() override {
-        base_t::counter = 0;
+        StaticSetUp();
+    }
+
+    void TearDown() override {
+        for(auto type: entt::resolve()) {
+            type.reset();
+        }
     }
 };
 
@@ -526,3 +545,12 @@ TEST_F(MetaData, FromBase) {
     ASSERT_TRUE(type.data("value"_hs).set(instance, 42));
     ASSERT_EQ(instance.value, 42);
 }
+
+TEST_F(MetaData, ReRegistration) {
+    MetaData::StaticSetUp();
+
+    auto *node = entt::internal::meta_info<base_t>::resolve();
+
+    ASSERT_NE(node->data, nullptr);
+    ASSERT_EQ(node->data->next, nullptr);
+}

+ 57 - 0
test/entt/meta/meta_dtor.cpp

@@ -0,0 +1,57 @@
+#include <gtest/gtest.h>
+#include <entt/meta/factory.hpp>
+#include <entt/meta/meta.hpp>
+#include <entt/meta/node.hpp>
+#include <entt/meta/resolve.hpp>
+
+struct clazz_t {
+    clazz_t() {
+        ++counter;
+    }
+
+    static void destroy(clazz_t &) {
+        --counter;
+    }
+
+    inline static int counter = 0;
+};
+
+struct MetaDtor: ::testing::Test {
+    static void StaticSetUp() {
+        using namespace entt::literals;
+
+        entt::meta<clazz_t>()
+            .type("clazz"_hs)
+            .dtor<&clazz_t::destroy>();
+    }
+
+    void SetUp() override {
+        StaticSetUp();
+    }
+
+    void TearDown() override {
+        for(auto type: entt::resolve()) {
+            type.reset();
+        }
+    }
+};
+
+TEST_F(MetaDtor, Functionalities) {
+    ASSERT_EQ(clazz_t::counter, 0);
+
+    auto any = entt::resolve<clazz_t>().construct();
+
+    ASSERT_EQ(clazz_t::counter, 1);
+
+    any.reset();
+
+    ASSERT_EQ(clazz_t::counter, 0);
+}
+
+TEST_F(MetaDtor, ReRegistration) {
+    MetaDtor::StaticSetUp();
+
+    auto *node = entt::internal::meta_info<clazz_t>::resolve();
+
+    ASSERT_NE(node->dtor, nullptr);
+}

+ 34 - 6
test/entt/meta/meta_func.cpp

@@ -60,14 +60,25 @@ struct func_t {
 };
 
 struct MetaFunc: ::testing::Test {
-    static void SetUpTestCase() {
+    void StaticSetUp() {
         using namespace entt::literals;
 
-        entt::meta<double>().conv<int>();
-        entt::meta<base_t>().dtor<&base_t::destroy>().func<&base_t::func>("func"_hs);
-        entt::meta<derived_t>().base<base_t>().dtor<&derived_t::destroy>();
+        entt::meta<double>()
+            .type("double"_hs)
+            .conv<int>();
 
-        entt::meta<func_t>().type("func"_hs)
+        entt::meta<base_t>()
+            .type("base"_hs)
+            .dtor<&base_t::destroy>()
+            .func<&base_t::func>("func"_hs);
+
+        entt::meta<derived_t>()
+            .type("derived"_hs)
+            .base<base_t>()
+            .dtor<&derived_t::destroy>();
+
+        entt::meta<func_t>()
+            .type("func"_hs)
             .func<&entt::registry::emplace_or_replace<func_t>, entt::as_ref_t>("emplace"_hs)
             .func<entt::overload<int(const base_t &, int, int)>(&func_t::f)>("f3"_hs)
             .func<entt::overload<int(int, int)>(&func_t::f)>("f2"_hs).prop(true, false)
@@ -78,10 +89,18 @@ struct MetaFunc: ::testing::Test {
             .func<&func_t::v, entt::as_void_t>("v"_hs)
             .func<&func_t::a, entt::as_ref_t>("a"_hs)
             .func<&func_t::a, entt::as_cref_t>("ca"_hs);
+
+        base_t::counter = 0;
     }
 
     void SetUp() override {
-        base_t::counter = 0;
+        StaticSetUp();
+    }
+
+    void TearDown() override {
+        for(auto type: entt::resolve()) {
+            type.reset();
+        }
     }
 };
 
@@ -421,3 +440,12 @@ TEST_F(MetaFunc, ExternalMemberFunction) {
 
     ASSERT_TRUE(registry.all_of<func_t>(entity));
 }
+
+TEST_F(MetaFunc, ReRegistration) {
+    MetaFunc::StaticSetUp();
+
+    auto *node = entt::internal::meta_info<base_t>::resolve();
+
+    ASSERT_NE(node->func, nullptr);
+    ASSERT_EQ(node->func->next, nullptr);
+}

+ 8 - 1
test/entt/meta/meta_handle.cpp

@@ -12,13 +12,20 @@ struct clazz_t {
 };
 
 struct MetaHandle: ::testing::Test {
-    static void SetUpTestCase() {
+    void SetUp() override {
         using namespace entt::literals;
 
         entt::meta<clazz_t>()
+            .type("clazz"_hs)
             .func<&clazz_t::incr>("incr"_hs)
             .func<&clazz_t::decr>("decr"_hs);
     }
+
+    void TearDown() override {
+        for(auto type: entt::resolve()) {
+            type.reset();
+        }
+    }
 };
 
 TEST_F(MetaHandle, Functionalities) {

+ 32 - 4
test/entt/meta/meta_prop.cpp

@@ -9,12 +9,31 @@ struct base_2_t {};
 struct derived_t: base_1_t, base_2_t {};
 
 struct MetaProp: ::testing::Test {
-    static void SetUpTestCase() {
+    void StaticSetUp() {
         using namespace entt::literals;
 
-        entt::meta<base_1_t>().prop("int"_hs, 42);
-        entt::meta<base_2_t>().prop("bool"_hs, false);
-        entt::meta<derived_t>().base<base_1_t>().base<base_2_t>();
+        entt::meta<base_1_t>()
+            .type("base_1"_hs)
+            .prop("int"_hs, 42);
+
+        entt::meta<base_2_t>()
+            .type("base_2"_hs)
+            .prop("bool"_hs, false);
+
+        entt::meta<derived_t>()
+            .type("derived"_hs)
+            .base<base_1_t>()
+            .base<base_2_t>();
+    }
+
+    void SetUp() override {
+        StaticSetUp();
+    }
+
+    void TearDown() override {
+        for(auto type: entt::resolve()) {
+            type.reset();
+        }
     }
 };
 
@@ -41,3 +60,12 @@ TEST_F(MetaProp, FromBase) {
     ASSERT_FALSE(prop_bool.value().cast<bool>());
     ASSERT_EQ(prop_int.value().cast<int>(), 42);
 }
+
+TEST_F(MetaProp, ReRegistration) {
+    MetaProp::StaticSetUp();
+
+    auto *node = entt::internal::meta_info<base_2_t>::resolve();
+
+    ASSERT_NE(node->prop, nullptr);
+    ASSERT_EQ(node->prop->next, nullptr);
+}

+ 7 - 1
test/entt/meta/meta_range.cpp

@@ -6,12 +6,18 @@
 #include <entt/meta/resolve.hpp>
 
 struct MetaRange: ::testing::Test {
-    static void SetUpTestCase() {
+    void SetUp() override {
         using namespace entt::literals;
 
         entt::meta<int>().type("int"_hs);
         entt::meta<double>().type("double"_hs);
     }
+
+    void TearDown() override {
+        for(auto type: entt::resolve()) {
+            type.reset();
+        }
+    }
 };
 
 TEST_F(MetaRange, Range) {

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

@@ -92,17 +92,38 @@ union union_t {
 };
 
 struct MetaType: ::testing::Test {
-    static void SetUpTestCase() {
+    void StaticSetUp() {
         using namespace entt::literals;
 
-        entt::meta<double>().type("double"_hs).conv<int>().data<&set<double>, &get<double>>("var"_hs);
-        entt::meta<unsigned int>().data<0u>("min"_hs).data<100u>("max"_hs);
-        entt::meta<base_t>().type("base"_hs).data<&base_t::value>("value"_hs);
-        entt::meta<derived_t>().type("derived"_hs).base<base_t>();
-        entt::meta<abstract_t>().func<&abstract_t::func>("func"_hs);
-        entt::meta<concrete_t>().base<base_t>().base<abstract_t>();
+        entt::meta<double>()
+            .type("double"_hs)
+            .conv<int>()
+            .data<&set<double>, &get<double>>("var"_hs);
 
-        entt::meta<overloaded_func_t>().type("overloaded_func"_hs)
+        entt::meta<unsigned int>()
+            .type("unsigned int"_hs)
+            .data<0u>("min"_hs)
+            .data<100u>("max"_hs);
+
+        entt::meta<base_t>()
+            .type("base"_hs)
+            .data<&base_t::value>("value"_hs);
+
+        entt::meta<derived_t>()
+            .type("derived"_hs)
+            .base<base_t>();
+
+        entt::meta<abstract_t>()
+            .type("abstract"_hs)
+            .func<&abstract_t::func>("func"_hs);
+
+        entt::meta<concrete_t>()
+            .type("concrete"_hs)
+            .base<base_t>()
+            .base<abstract_t>();
+
+        entt::meta<overloaded_func_t>()
+            .type("overloaded_func"_hs)
             .func<&overloaded_func_t::e> ("e"_hs)
             .func<entt::overload<int(const base_t &, int, int)>(&overloaded_func_t::f)>("f"_hs)
             .func<entt::overload<int(int, int)>(&overloaded_func_t::f)>("f"_hs)
@@ -111,6 +132,7 @@ struct MetaType: ::testing::Test {
             .func<&overloaded_func_t::g> ("g"_hs);
 
         entt::meta<property_t>()
+            .type("property"_hs)
             .data<property_t::random>("random"_hs)
                 .prop(property_t::random, 0)
                 .prop(property_t::value, 3)
@@ -131,6 +153,16 @@ struct MetaType: ::testing::Test {
             .func<&clazz_t::member>("member"_hs)
             .func<&clazz_t::func>("func"_hs);
     }
+
+    void SetUp() override {
+        StaticSetUp();
+    }
+
+    void TearDown() override {
+        for(auto type: entt::resolve()) {
+            type.reset();
+        }
+    }
 };
 
 TEST_F(MetaType, Resolve) {
@@ -464,6 +496,28 @@ TEST_F(MetaType, Reset) {
     ASSERT_TRUE(entt::resolve<clazz_t>().ctor<>());
 }
 
+TEST_F(MetaType, ResetAll) {
+    using namespace entt::literals;
+
+    ASSERT_NE(entt::resolve().begin(), entt::resolve().end());
+
+    ASSERT_TRUE(entt::resolve("clazz"_hs));
+    ASSERT_TRUE(entt::resolve("overloaded_func"_hs));
+    ASSERT_TRUE(entt::resolve("double"_hs));
+
+    for(auto type: entt::resolve()) {
+        // we exploit the fact that the iterators aren't invalidated
+        // because EnTT leaves a dangling ::next in the underlying node
+        type.reset();
+    }
+
+    ASSERT_FALSE(entt::resolve("clazz"_hs));
+    ASSERT_FALSE(entt::resolve("overloaded_func"_hs));
+    ASSERT_FALSE(entt::resolve("double"_hs));
+
+    ASSERT_EQ(entt::resolve().begin(), entt::resolve().end());
+}
+
 TEST_F(MetaType, AbstractClass) {
     using namespace entt::literals;
 
@@ -594,7 +648,11 @@ TEST_F(MetaType, ResetAndReRegistrationAfterReset) {
     ASSERT_FALSE(entt::resolve("derived"_hs));
     ASSERT_TRUE(entt::resolve("double"_hs));
 
-    entt::meta<property_t>().data<property_t::random>("rand"_hs).prop(property_t::value, 42).prop(property_t::random, 3);
+    entt::meta<property_t>()
+        .type("property"_hs)
+        .data<property_t::random>("rand"_hs)
+        .prop(property_t::value, 42)
+        .prop(property_t::random, 3);
 
     ASSERT_TRUE(entt::resolve<property_t>().data("rand"_hs).prop(property_t::value));
     ASSERT_TRUE(entt::resolve<property_t>().data("rand"_hs).prop(property_t::random));
@@ -612,3 +670,19 @@ TEST_F(MetaType, ClassTemplate) {
     ASSERT_EQ(entt::resolve<std::shared_ptr<int>>().template_arg(0u), entt::resolve<int>());
     ASSERT_EQ(entt::resolve<std::shared_ptr<int>>().template_arg(1u), entt::meta_type{});
 }
+
+TEST_F(MetaType, ReRegistration) {
+    int count = 0;
+
+    for(auto type: entt::resolve()) {
+        ++count;
+    }
+
+    MetaType::StaticSetUp();
+
+    for(auto type: entt::resolve()) {
+        --count;
+    }
+
+    ASSERT_EQ(count, 0);
+}