Jelajahi Sumber

registry: assert when emplacing invalid entities - close #1095

Michele Caini 2 tahun lalu
induk
melakukan
83aabf7cfc
2 mengubah file dengan 20 tambahan dan 0 penghapusan
  1. 5 0
      src/entt/entity/registry.hpp
  2. 15 0
      test/entt/entity/registry.cpp

+ 5 - 0
src/entt/entity/registry.hpp

@@ -583,6 +583,7 @@ public:
      */
     template<typename Type, typename... Args>
     decltype(auto) emplace(const entity_type entt, Args &&...args) {
+        ENTT_ASSERT(valid(entt), "Invalid entity");
         return assure<Type>().emplace(entt, std::forward<Args>(args)...);
     }
 
@@ -599,6 +600,7 @@ public:
      */
     template<typename Type, typename It>
     void insert(It first, It last, const Type &value = {}) {
+        ENTT_ASSERT(std::all_of(first, last, [this](const auto entt) { return valid(entt); }), "Invalid entity");
         assure<Type>().insert(std::move(first), std::move(last), value);
     }
 
@@ -616,6 +618,7 @@ public:
      */
     template<typename Type, typename EIt, typename CIt, typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<CIt>::value_type, Type>>>
     void insert(EIt first, EIt last, CIt from) {
+        ENTT_ASSERT(std::all_of(first, last, [this](const auto entt) { return valid(entt); }), "Invalid entity");
         assure<Type>().insert(first, last, from);
     }
 
@@ -636,6 +639,7 @@ public:
         if(auto &cpool = assure<Type>(); cpool.contains(entt)) {
             return cpool.patch(entt, [&args...](auto &...curr) { ((curr = Type{std::forward<Args>(args)...}), ...); });
         } else {
+            ENTT_ASSERT(valid(entt), "Invalid entity");
             return cpool.emplace(entt, std::forward<Args>(args)...);
         }
     }
@@ -899,6 +903,7 @@ public:
         if(auto &cpool = assure<Type>(); cpool.contains(entt)) {
             return cpool.get(entt);
         } else {
+            ENTT_ASSERT(valid(entt), "Invalid entity");
             return cpool.emplace(entt, std::forward<Args>(args)...);
         }
     }

+ 15 - 0
test/entt/entity/registry.cpp

@@ -446,6 +446,20 @@ TEST(Registry, Swap) {
     ASSERT_EQ(test.parent, &registry);
 }
 
+TEST(RegistryDeathTest, EmplaceInvalidEntity) {
+    entt::registry registry;
+    const std::array entity{registry.create()};
+    const std::array value{0};
+
+    registry.destroy(entity[0]);
+
+    ASSERT_DEATH(registry.emplace<int>(entity[0u]), "");
+    ASSERT_DEATH(registry.insert<int>(entity.begin(), entity.end(), value[0]), "");
+    ASSERT_DEATH(registry.insert<int>(entity.begin(), entity.end(), value.begin()), "");
+    ASSERT_DEATH(registry.emplace_or_replace<int>(entity[0u]), "");
+    ASSERT_DEATH([[maybe_unused]] const auto value = registry.get_or_emplace<int>(entity[0u]), "");
+}
+
 TEST(Registry, ReplaceAggregate) {
     entt::registry registry;
     const auto entity = registry.create();
@@ -1894,6 +1908,7 @@ TEST(Registry, GetOrEmplace) {
     entt::registry registry;
     const auto entity = registry.create();
     const auto value = registry.get_or_emplace<int>(entity, 3);
+
     // get_or_emplace must work for empty types
     static_cast<void>(registry.get_or_emplace<test::empty>(entity));