diff --git a/src/entt/entity/sigh_storage_mixin.hpp b/src/entt/entity/sigh_storage_mixin.hpp index 672cf3b06..66b1fbdee 100644 --- a/src/entt/entity/sigh_storage_mixin.hpp +++ b/src/entt/entity/sigh_storage_mixin.hpp @@ -27,26 +27,17 @@ class sigh_storage_mixin final: public Type { using sigh_type = sigh &, const typename Type::entity_type), typename Type::allocator_type>; using basic_iterator = typename Type::basic_iterator; - template - void notify_destruction(basic_iterator first, basic_iterator last, Func func) { + void pop(basic_iterator first, basic_iterator last) override { ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry"); for(; first != last; ++first) { const auto entt = *first; destruction.publish(*owner, entt); const auto it = Type::find(entt); - func(it, it + 1u); + Type::pop(it, it + 1u); } } - void swap_and_pop(basic_iterator first, basic_iterator last) final { - notify_destruction(std::move(first), std::move(last), [this](auto... args) { Type::swap_and_pop(args...); }); - } - - void in_place_pop(basic_iterator first, basic_iterator last) final { - notify_destruction(std::move(first), std::move(last), [this](auto... args) { Type::in_place_pop(args...); }); - } - basic_iterator try_emplace(const typename Type::entity_type entt, const bool force_back, const void *value) final { ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry"); Type::try_emplace(entt, force_back, value); diff --git a/src/entt/entity/sparse_set.hpp b/src/entt/entity/sparse_set.hpp index ada88c398..ab12723ec 100644 --- a/src/entt/entity/sparse_set.hpp +++ b/src/entt/entity/sparse_set.hpp @@ -234,31 +234,43 @@ protected: using basic_iterator = internal::sparse_set_iterator; /** - * @brief Erases entities from a sparse set. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. + * @brief Erases an entity from a sparse set. + * @param it An iterator to the element to pop. */ - virtual void swap_and_pop(basic_iterator first, basic_iterator last) { - for(; first != last; ++first) { - sparse_ref(packed.back()) = entity_traits::combine(static_cast(first.index()), entity_traits::to_integral(packed.back())); - const auto entt = std::exchange(packed[first.index()], packed.back()); - // unnecessary but it helps to detect nasty bugs - ENTT_ASSERT((packed.back() = null, true), ""); - // lazy self-assignment guard - sparse_ref(entt) = null; - packed.pop_back(); - } + void swap_and_pop(const basic_iterator it) { + sparse_ref(packed.back()) = entity_traits::combine(static_cast(it.index()), entity_traits::to_integral(packed.back())); + const auto entt = std::exchange(packed[it.index()], packed.back()); + // unnecessary but it helps to detect nasty bugs + ENTT_ASSERT((packed.back() = null, true), ""); + // lazy self-assignment guard + sparse_ref(entt) = null; + packed.pop_back(); } + /** + * @brief Erases an entity from a sparse set. + * @param it An iterator to the element to pop. + */ + void in_place_pop(const basic_iterator it) { + sparse_ref(*it) = null; + packed[it.index()] = std::exchange(free_list, entity_traits::combine(static_cast(it.index()), entity_traits::reserved)); + } + +protected: /** * @brief Erases entities from a sparse set. * @param first An iterator to the first element of the range of entities. * @param last An iterator past the last element of the range of entities. */ - virtual void in_place_pop(basic_iterator first, basic_iterator last) { - for(; first != last; ++first) { - sparse_ref(*first) = null; - packed[first.index()] = std::exchange(free_list, entity_traits::combine(static_cast(first.index()), entity_traits::reserved)); + virtual void pop(basic_iterator first, basic_iterator last) { + if(mode == deletion_policy::in_place) { + for(; first != last; ++first) { + in_place_pop(first); + } + } else { + for(; first != last; ++first) { + swap_and_pop(first); + } } } @@ -710,7 +722,7 @@ public: */ void erase(const entity_type entt) { const auto it = --(end() - index(entt)); - (mode == deletion_policy::in_place) ? in_place_pop(it, it + 1u) : swap_and_pop(it, it + 1u); + pop(it, it + 1u); } /** @@ -725,7 +737,7 @@ public: template void erase(It first, It last) { if constexpr(std::is_same_v) { - (mode == deletion_policy::in_place) ? in_place_pop(first, last) : swap_and_pop(first, last); + pop(first, last); } else { for(; first != last; ++first) { erase(*first); @@ -922,12 +934,12 @@ public: /*! @brief Clears a sparse set. */ void clear() { if(const auto last = end(); free_list == null) { - in_place_pop(begin(), last); + pop(begin(), last); } else { for(auto &&entity: *this) { // tombstone filter on itself if(const auto it = find(entity); it != last) { - in_place_pop(it, it + 1u); + pop(it, it + 1u); } } } diff --git a/src/entt/entity/storage.hpp b/src/entt/entity/storage.hpp index 70780a766..47d1fc02a 100644 --- a/src/entt/entity/storage.hpp +++ b/src/entt/entity/storage.hpp @@ -275,12 +275,7 @@ class basic_storage: public basic_sparse_set(args)...); } ENTT_CATCH { - if constexpr(comp_traits::in_place_delete) { - base_type::in_place_pop(it, it + 1u); - } else { - base_type::swap_and_pop(it, it + 1u); - } - + base_type::pop(it, it + 1u); ENTT_THROW; } @@ -330,29 +325,22 @@ protected: using basic_iterator = typename underlying_type::basic_iterator; /** - * @brief Erases elements from a storage. - * @param first An iterator to the first element to erase. - * @param last An iterator past the last element to erase. + * @brief Erases entities from a sparse set. + * @param first An iterator to the first element of the range of entities. + * @param last An iterator past the last element of the range of entities. */ - void swap_and_pop(basic_iterator first, basic_iterator last) override { + void pop(basic_iterator first, basic_iterator last) override { for(; first != last; ++first) { - auto &elem = element_at(base_type::size() - 1u); - // destroying on exit allows reentrant destructors - [[maybe_unused]] auto unused = std::exchange(element_at(static_cast(first.index())), std::move(elem)); - std::destroy_at(std::addressof(elem)); - base_type::swap_and_pop(first, first + 1u); - } - } - - /** - * @brief Erases elements from a storage. - * @param first An iterator to the first element to erase. - * @param last An iterator past the last element to erase. - */ - void in_place_pop(basic_iterator first, basic_iterator last) override { - for(; first != last; ++first) { - base_type::in_place_pop(first, first + 1u); - std::destroy_at(std::addressof(element_at(static_cast(first.index())))); + if constexpr(comp_traits::in_place_delete) { + base_type::in_place_pop(first); + std::destroy_at(std::addressof(element_at(static_cast(first.index())))); + } else { + auto &elem = element_at(base_type::size() - 1u); + // destroying on exit allows reentrant destructors + [[maybe_unused]] auto unused = std::exchange(element_at(static_cast(first.index())), std::move(elem)); + std::destroy_at(std::addressof(elem)); + base_type::swap_and_pop(first); + } } }