Browse Source

sigh_mixin: make pop_all use narrow view iterators if any

Michele Caini 3 years ago
parent
commit
3762189916
2 changed files with 46 additions and 3 deletions
  1. 6 3
      src/entt/entity/mixin.hpp
  2. 40 0
      test/entt/entity/sigh_mixin.cpp

+ 6 - 3
src/entt/entity/mixin.hpp

@@ -48,13 +48,16 @@ class sigh_mixin final: public Type {
         if(!destruction.empty()) {
         if(!destruction.empty()) {
             ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
             ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
 
 
-            for(auto &&entt: static_cast<typename Type::base_type &>(*this)) {
+            const auto iterable = Type::each();
+            const auto last = iterable.end().base();
+
+            for(auto first = iterable.begin().base(); first != last; ++first) {
                 if constexpr(Type::traits_type::in_place_delete) {
                 if constexpr(Type::traits_type::in_place_delete) {
-                    if(entt != tombstone) {
+                    if(const auto entt = *first; entt != tombstone) {
                         destruction.publish(*owner, entt);
                         destruction.publish(*owner, entt);
                     }
                     }
                 } else {
                 } else {
-                    destruction.publish(*owner, entt);
+                    destruction.publish(*owner, *first);
                 }
                 }
             }
             }
         }
         }

+ 40 - 0
test/entt/entity/sigh_mixin.cpp

@@ -31,6 +31,17 @@ void listener(counter &counter, Registry &, typename Registry::entity_type) {
     ++counter.value;
     ++counter.value;
 }
 }
 
 
+struct empty_each_tag final {};
+
+template<>
+struct entt::basic_storage<empty_each_tag, entt::entity, std::allocator<empty_each_tag>>: entt::basic_storage<void, entt::entity, std::allocator<void>> {
+    basic_storage(const std::allocator<empty_each_tag> &) {}
+
+    [[nodiscard]] iterable each() noexcept {
+        return {internal::extended_storage_iterator{base_type::end()}, internal::extended_storage_iterator{base_type::end()}};
+    }
+};
+
 TEST(SighMixin, GenericType) {
 TEST(SighMixin, GenericType) {
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
     entt::sigh_mixin<entt::storage<int>> pool;
     entt::sigh_mixin<entt::storage<int>> pool;
@@ -423,6 +434,35 @@ TEST(SighMixin, Swap) {
     ASSERT_EQ(on_destroy.value, 3);
     ASSERT_EQ(on_destroy.value, 3);
 }
 }
 
 
+TEST(SighMixin, EmptyEachStorage) {
+    entt::sigh_mixin<entt::storage<empty_each_tag>> pool;
+    entt::registry registry;
+
+    counter on_destroy{};
+
+    pool.bind(entt::forward_as_any(registry));
+    pool.on_destroy().connect<&listener<entt::registry>>(on_destroy);
+
+    ASSERT_TRUE(pool.empty());
+    ASSERT_EQ(on_destroy.value, 0);
+
+    pool.push(entt::entity{42});
+
+    ASSERT_FALSE(pool.empty());
+    ASSERT_EQ(on_destroy.value, 0);
+
+    ASSERT_NE(pool.begin(), pool.end());
+    ASSERT_EQ(pool.each().begin(), pool.each().end());
+    ASSERT_EQ(on_destroy.value, 0);
+
+    pool.clear();
+
+    ASSERT_EQ(pool.begin(), pool.end());
+    ASSERT_EQ(pool.each().begin(), pool.each().end());
+    // no signal at all because of the (fake) empty iterable
+    ASSERT_EQ(on_destroy.value, 0);
+}
+
 TEST(SighMixin, CustomAllocator) {
 TEST(SighMixin, CustomAllocator) {
     auto test = [](auto pool, auto alloc) {
     auto test = [](auto pool, auto alloc) {
         using registry_type = typename decltype(pool)::registry_type;
         using registry_type = typename decltype(pool)::registry_type;