Sfoglia il codice sorgente

sparse_set/storage: drop move_element

Michele Caini 3 anni fa
parent
commit
ed4c675211
3 ha cambiato i file con 58 aggiunte e 15 eliminazioni
  1. 2 2
      src/entt/entity/sparse_set.hpp
  2. 12 13
      src/entt/entity/storage.hpp
  3. 44 0
      test/entt/entity/storage.cpp

+ 2 - 2
src/entt/entity/sparse_set.hpp

@@ -226,7 +226,6 @@ private:
     }
 
     virtual void swap_at(const std::size_t, const std::size_t) {}
-    virtual void move_element(const std::size_t, const std::size_t) {}
 
 protected:
     /*! @brief Random access iterator type. */
@@ -785,7 +784,7 @@ public:
         for(auto *it = &free_list; *it != null && from; it = std::addressof(packed[traits_type::to_entity(*it)])) {
             if(const size_type to = traits_type::to_entity(*it); to < from) {
                 --from;
-                move_element(from, to);
+                swap_at(from, to);
 
                 using std::swap;
                 swap(packed[from], packed[to]);
@@ -825,6 +824,7 @@ public:
 
         // basic no-leak guarantee (with invalid state) if swapping throws
         swap_at(static_cast<size_type>(from), static_cast<size_type>(to));
+
         entt = traits_type::combine(to, traits_type::to_integral(packed[from]));
         other = traits_type::combine(from, traits_type::to_integral(packed[to]));
 

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

@@ -305,24 +305,23 @@ private:
         return std::addressof(element_at(pos));
     }
 
-    void swap_at([[maybe_unused]] const std::size_t lhs, [[maybe_unused]] const std::size_t rhs) final {
-        // use a runtime value to avoid compile-time suppression that drives the code coverage tool crazy
-        ENTT_ASSERT((lhs + 1u) && !is_pinned_type_v, "Pinned type");
-
-        if constexpr(!is_pinned_type_v) {
-            using std::swap;
-            swap(element_at(lhs), element_at(rhs));
-        }
-    }
-
-    void move_element([[maybe_unused]] const std::size_t from, [[maybe_unused]] const std::size_t to) final {
+    void swap_at([[maybe_unused]] const std::size_t from, [[maybe_unused]] const std::size_t to) final {
         // use a runtime value to avoid compile-time suppression that drives the code coverage tool crazy
         ENTT_ASSERT((from + 1u) && !is_pinned_type_v, "Pinned type");
 
         if constexpr(!is_pinned_type_v) {
             auto &elem = element_at(from);
-            entt::uninitialized_construct_using_allocator(to_address(assure_at_least(to)), get_allocator(), std::move(elem));
-            std::destroy_at(std::addressof(elem));
+
+            if constexpr(traits_type::in_place_delete) {
+                if(base_type::operator[](to) == tombstone) {
+                    entt::uninitialized_construct_using_allocator(to_address(assure_at_least(to)), get_allocator(), std::move(elem));
+                    std::destroy_at(std::addressof(elem));
+                    return;
+                }
+            }
+
+            using std::swap;
+            swap(elem, element_at(to));
         }
     }
 

+ 44 - 0
test/entt/entity/storage.cpp

@@ -1364,6 +1364,50 @@ TEST(Storage, Raw) {
     ASSERT_EQ(pool.raw()[0u][2u], 9);
 }
 
+TEST(Storage, SwapElements) {
+    entt::storage<int> pool;
+
+    pool.emplace(entt::entity{3}, 3);
+    pool.emplace(entt::entity{12}, 6);
+    pool.emplace(entt::entity{42}, 9);
+
+    pool.erase(entt::entity{12});
+
+    ASSERT_EQ(pool.get(entt::entity{3}), 3);
+    ASSERT_EQ(pool.get(entt::entity{42}), 9);
+    ASSERT_EQ(pool.index(entt::entity{3}), 0u);
+    ASSERT_EQ(pool.index(entt::entity{42}), 1u);
+
+    pool.swap_elements(entt::entity{3}, entt::entity{42});
+
+    ASSERT_EQ(pool.get(entt::entity{3}), 3);
+    ASSERT_EQ(pool.get(entt::entity{42}), 9);
+    ASSERT_EQ(pool.index(entt::entity{3}), 1u);
+    ASSERT_EQ(pool.index(entt::entity{42}), 0u);
+}
+
+TEST(Storage, StableSwapElements) {
+    entt::storage<stable_type> pool;
+
+    pool.emplace(entt::entity{3}, 3);
+    pool.emplace(entt::entity{12}, 6);
+    pool.emplace(entt::entity{42}, 9);
+
+    pool.erase(entt::entity{12});
+
+    ASSERT_EQ(pool.get(entt::entity{3}).value, 3);
+    ASSERT_EQ(pool.get(entt::entity{42}).value, 9);
+    ASSERT_EQ(pool.index(entt::entity{3}), 0u);
+    ASSERT_EQ(pool.index(entt::entity{42}), 2u);
+
+    pool.swap_elements(entt::entity{3}, entt::entity{42});
+
+    ASSERT_EQ(pool.get(entt::entity{3}).value, 3);
+    ASSERT_EQ(pool.get(entt::entity{42}).value, 9);
+    ASSERT_EQ(pool.index(entt::entity{3}), 2u);
+    ASSERT_EQ(pool.index(entt::entity{42}), 0u);
+}
+
 TEST(Storage, SortOrdered) {
     entt::storage<boxed_int> pool;
     entt::entity entities[5u]{entt::entity{12}, entt::entity{42}, entt::entity{7}, entt::entity{3}, entt::entity{9}};