Browse Source

sparse_set: merge ::swap_and_pop and ::in_place_pop

Michele Caini 4 years ago
parent
commit
1c6670c7a1
2 changed files with 27 additions and 44 deletions
  1. 14 18
      src/entt/entity/sparse_set.hpp
  2. 13 26
      src/entt/entity/storage.hpp

+ 14 - 18
src/entt/entity/sparse_set.hpp

@@ -236,23 +236,19 @@ protected:
      * @brief Erases an entity from a sparse set.
      * @param pos A valid position of an element within a sparse set.
      */
-    virtual void swap_and_pop(const std::size_t pos) {
-        sparse_ref(packed.back()) = entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), entity_traits::to_integral(packed.back()));
-        // lazy self-assignment guard
-        sparse_ref(packed[pos]) = null;
-        packed[pos] = packed.back();
-        // unnecessary but it helps to detect nasty bugs
-        ENTT_ASSERT((packed.back() = tombstone, true), "");
-        packed.pop_back();
-    }
-
-    /**
-     * @brief Erases an entity from a sparse set.
-     * @param pos A valid position of an element within a sparse set.
-     */
-    virtual void in_place_pop(const std::size_t pos) {
-        sparse_ref(packed[pos]) = null;
-        packed[pos] = std::exchange(free_list, entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), entity_traits::reserved));
+    virtual void pop_at(const std::size_t pos) {
+        if(mode == deletion_policy::in_place) {
+            sparse_ref(packed[pos]) = null;
+            packed[pos] = std::exchange(free_list, entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), entity_traits::reserved));
+        } else {
+            sparse_ref(packed.back()) = entity_traits::combine(static_cast<typename entity_traits::entity_type>(pos), entity_traits::to_integral(packed.back()));
+            // lazy self-assignment guard
+            sparse_ref(packed[pos]) = null;
+            packed[pos] = packed.back();
+            // unnecessary but it helps to detect nasty bugs
+            ENTT_ASSERT((packed.back() = tombstone, true), "");
+            packed.pop_back();
+        }
     }
 
     /**
@@ -696,7 +692,7 @@ public:
      * @param entt A valid identifier.
      */
     void erase(const entity_type entt) {
-        (mode == deletion_policy::in_place) ? in_place_pop(index(entt)) : swap_and_pop(index(entt));
+        pop_at(index(entt));
         ENTT_ASSERT(!contains(entt), "Destruction did not take place");
     }
 

+ 13 - 26
src/entt/entity/storage.hpp

@@ -326,23 +326,17 @@ protected:
      * @brief Erases an element from a storage.
      * @param pos A valid position of an element within a storage.
      */
-    void swap_and_pop(const std::size_t pos) override {
-        auto &elem = element_at(base_type::size() - 1u);
-        // support for nosy destructors
-        [[maybe_unused]] auto unused = std::exchange(element_at(pos), std::move(elem));
-        base_type::swap_and_pop(pos);
-        std::destroy_at(std::addressof(elem));
-    }
-
-    /**
-     * @brief Erases an element from a storage.
-     * @param pos A valid position of an element within a storage.
-     */
-    void in_place_pop(const std::size_t pos) override {
-        auto &elem = element_at(pos);
-        base_type::in_place_pop(pos);
-        // support for nosy destructors
-        std::destroy_at(std::addressof(elem));
+    void pop_at(const std::size_t pos) override {
+        if constexpr(comp_traits::in_place_delete) {
+            std::destroy_at(std::addressof(element_at(pos)));
+            base_type::pop_at(pos);
+        } else {
+            auto &elem = element_at(base_type::size() - 1u);
+            // support chained destructors i.e. parent-to-child propagation
+            [[maybe_unused]] auto unused = std::exchange(element_at(pos), std::move(elem));
+            std::destroy_at(std::addressof(elem));
+            base_type::pop_at(pos);
+        }
     }
 
     /**
@@ -912,18 +906,11 @@ public:
  */
 template<typename Type>
 class sigh_storage_mixin final: public Type {
-    void swap_and_pop(const std::size_t pos) final {
-        ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
-        const auto entt = Type::operator[](pos);
-        destruction.publish(*owner, entt);
-        Type::swap_and_pop(Type::index(entt));
-    }
-
-    void in_place_pop(const std::size_t pos) final {
+    void pop_at(const std::size_t pos) final {
         ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
         const auto entt = Type::operator[](pos);
         destruction.publish(*owner, entt);
-        Type::in_place_pop(Type::index(entt));
+        Type::pop_at(Type::index(entt));
     }
 
     void try_emplace(const typename Type::entity_type entt, const void *value) final {