Kaynağa Gözat

sparse_set/storage: rollback ::policy(pol), incompatible with views

Michele Caini 4 yıl önce
ebeveyn
işleme
9fb1970ac0

+ 6 - 20
docs/md/entity.md

@@ -1004,18 +1004,11 @@ within the storage, making direct access almost impossible (be it via pointer or
 index).
 
 However, the underlying model with its independent pools helps introduce storage
-with different deletion policies, so that users can best choose type by
-type.<br/>
-In particular, the library offers out of the box support for in-place deletion,
-thus offering storage with completely stable pointers. There are two options to
-achieve it:
-
-* A compile-time method, which is to specialize the `component_traits` class.
-* A runtime method, which is to set the deletion policy for a pool manually.
-
-Also, there is no problem changing the deletion policy at runtime, even when a
-compile-time policy exists.<br/>
-The compile-time definition common to all components is the following:
+with different deletion policies. In particular, the library offers out of the
+box support for in-place deletion, thus offering storage with completely stable
+pointers.<br/>
+This is done by specializing the `component_traits` class. The compile-time
+definition common to all components is the following:
 
 ```cpp
 struct basic_component_traits {
@@ -1040,18 +1033,11 @@ struct entt::component_traits<position>: basic_component_traits {
 
 This will ensure in-place deletion for the `position` component without further
 user intervention.<br/>
-Changing the deletion policy at runtime is instead reduced to a direct call on
-the pool itself:
-
-```cpp
-registry.storage<position>().policy(entt::deletion_policy::in_place);
-```
-
 Views and groups adapt accordingly when they detect a storage with a different
 deletion policy than the default. No specific action is required from the user
 once in-place deletion is enabled. In particular:
 
-* Groups are incompatible with stable storage and will trigger a runtime error.
+* Groups are incompatible with stable storage and will even refuse to compile.
 * Multi type views are completely transparent to storage policies.
 * Single type views for stable storage types offer the same interface of multi
   type views. For example, only `size_hint` is available.

+ 3 - 5
src/entt/entity/registry.hpp

@@ -182,12 +182,13 @@ class basic_registry {
 
     template<typename... Exclude, typename... Get, typename... Owned>
     struct group_handler<exclude_t<Exclude...>, get_t<Get...>, Owned...> {
+        // nasty workaround for an issue with the toolset v141 that doesn't accept a fold expression here
+        static_assert(!std::disjunction_v<std::bool_constant<component_traits<Owned>::in_place_delete>...>, "Groups do not support in-place delete");
         std::conditional_t<sizeof...(Owned) == 0, basic_common_type, std::size_t> current{};
 
         template<typename Component>
         void maybe_valid_if(basic_registry &owner, const Entity entt) {
             [[maybe_unused]] const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...);
-            ENTT_ASSERT(((std::get<storage_type<Owned> &>(cpools).policy() == deletion_policy::swap_and_pop) && ...), "Groups do not support in-place delete");
 
             const auto is_valid = ((std::is_same_v<Component, Owned> || std::get<storage_type<Owned> &>(cpools).contains(entt)) && ...)
                                   && ((std::is_same_v<Component, Get> || owner.assure<Get>().contains(entt)) && ...)
@@ -209,10 +210,7 @@ class basic_registry {
             if constexpr(sizeof...(Owned) == 0) {
                 current.remove(entt);
             } else {
-                const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...);
-                ENTT_ASSERT(((std::get<storage_type<Owned> &>(cpools).policy() == deletion_policy::swap_and_pop) && ...), "Groups do not support in-place delete");
-
-                if(std::get<0>(cpools).contains(entt) && (std::get<0>(cpools).index(entt) < current)) {
+                if(const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...); std::get<0>(cpools).contains(entt) && (std::get<0>(cpools).index(entt) < current)) {
                     const auto pos = --current;
                     (std::get<storage_type<Owned> &>(cpools).swap_elements(std::get<storage_type<Owned> &>(cpools).data()[pos], entt), ...);
                 }

+ 0 - 12
src/entt/entity/sparse_set.hpp

@@ -398,18 +398,6 @@ public:
         return mode;
     }
 
-    /**
-     * @brief Sets the deletion policy of a sparse set.
-     * @param pol The deletion policy of the sparse set.
-     */
-    void policy(const deletion_policy pol) ENTT_NOEXCEPT {
-        if(pol != mode && mode == deletion_policy::in_place) {
-            compact();
-        }
-
-        mode = pol;
-    }
-
     /**
      * @brief Returns the next slot available for insertion.
      * @return The next slot available for insertion.

+ 0 - 36
test/entt/entity/sparse_set.cpp

@@ -753,42 +753,6 @@ TEST(SparseSet, Compact) {
     ASSERT_TRUE(set.empty());
 }
 
-TEST(SparseSet, Policy) {
-    entt::sparse_set set{entt::deletion_policy::in_place};
-    entt::entity entities[3u]{entt::entity{0}, entt::entity{1}, entt::entity{2}};
-
-    set.insert(std::begin(entities), std::end(entities));
-    set.erase(entities[1u]);
-
-    ASSERT_EQ(set.size(), 3u);
-    ASSERT_EQ(set.index(entities[0u]), 0u);
-    ASSERT_FALSE(set.contains(entities[1u]));
-    ASSERT_EQ(set.index(entities[2u]), 2u);
-
-    set.policy(entt::deletion_policy::swap_and_pop);
-
-    ASSERT_EQ(set.size(), 2u);
-    ASSERT_EQ(set.index(entities[0u]), 0u);
-    ASSERT_EQ(set.index(entities[2u]), 1u);
-
-    set.erase(entities[0u]);
-
-    ASSERT_EQ(set.size(), 1u);
-    ASSERT_FALSE(set.contains(entities[0u]));
-    ASSERT_EQ(set.index(entities[2u]), 0u);
-
-    set.policy(entt::deletion_policy::in_place);
-    set.erase(entities[2u]);
-
-    ASSERT_EQ(set.size(), 1u);
-    ASSERT_FALSE(set.contains(entities[2u]));
-
-    set.policy(entt::deletion_policy::swap_and_pop);
-
-    ASSERT_EQ(set.size(), 0u);
-    ASSERT_TRUE(set.empty());
-}
-
 TEST(SparseSet, SwapEntity) {
     using traits_type = entt::entt_traits<entt::entity>;
 

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

@@ -772,49 +772,6 @@ TEST(Storage, Compact) {
     ASSERT_TRUE(pool.empty());
 }
 
-TEST(Storage, Policy) {
-    entt::storage<stable_type> pool{};
-    entt::entity entities[3u]{entt::entity{0}, entt::entity{1}, entt::entity{2}};
-
-    pool.emplace(entities[0u], stable_type{0});
-    pool.emplace(entities[1u], stable_type{1});
-    pool.emplace(entities[2u], stable_type{2});
-    pool.erase(entities[1u]);
-
-    ASSERT_EQ(pool.size(), 3u);
-    ASSERT_EQ(pool.index(entities[0u]), 0u);
-    ASSERT_FALSE(pool.contains(entities[1u]));
-    ASSERT_EQ(pool.index(entities[2u]), 2u);
-    ASSERT_EQ(pool.get(entities[0u]).value, 0);
-    ASSERT_EQ(pool.get(entities[2u]).value, 2);
-
-    pool.policy(entt::deletion_policy::swap_and_pop);
-
-    ASSERT_EQ(pool.size(), 2u);
-    ASSERT_EQ(pool.index(entities[0u]), 0u);
-    ASSERT_EQ(pool.index(entities[2u]), 1u);
-    ASSERT_EQ(pool.get(entities[0u]).value, 0);
-    ASSERT_EQ(pool.get(entities[2u]).value, 2);
-
-    pool.erase(entities[0u]);
-
-    ASSERT_EQ(pool.size(), 1u);
-    ASSERT_FALSE(pool.contains(entities[0u]));
-    ASSERT_EQ(pool.index(entities[2u]), 0u);
-    ASSERT_EQ(pool.get(entities[2u]).value, 2);
-
-    pool.policy(entt::deletion_policy::in_place);
-    pool.erase(entities[2u]);
-
-    ASSERT_EQ(pool.size(), 1u);
-    ASSERT_FALSE(pool.contains(entities[2u]));
-
-    pool.policy(entt::deletion_policy::swap_and_pop);
-
-    ASSERT_EQ(pool.size(), 0u);
-    ASSERT_TRUE(pool.empty());
-}
-
 TEST(Storage, ShrinkToFit) {
     entt::storage<int> pool;