sigh_mixin: make pop_all use narrow view iterators if any

This commit is contained in:
Michele Caini
2023-01-23 10:09:56 +01:00
parent 18d6e466d0
commit 3762189916
2 changed files with 46 additions and 3 deletions

View File

@@ -48,13 +48,16 @@ class sigh_mixin final: public Type {
if(!destruction.empty()) {
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(entt != tombstone) {
if(const auto entt = *first; entt != tombstone) {
destruction.publish(*owner, entt);
}
} else {
destruction.publish(*owner, entt);
destruction.publish(*owner, *first);
}
}
}

View File

@@ -31,6 +31,17 @@ void listener(counter &counter, Registry &, typename Registry::entity_type) {
++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) {
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
entt::sigh_mixin<entt::storage<int>> pool;
@@ -423,6 +434,35 @@ TEST(SighMixin, Swap) {
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) {
auto test = [](auto pool, auto alloc) {
using registry_type = typename decltype(pool)::registry_type;