Sfoglia il codice sorgente

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

Michele Caini 4 anni fa
parent
commit
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).
 index).
 
 
 However, the underlying model with its independent pools helps introduce storage
 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
 ```cpp
 struct basic_component_traits {
 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
 This will ensure in-place deletion for the `position` component without further
 user intervention.<br/>
 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
 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
 deletion policy than the default. No specific action is required from the user
 once in-place deletion is enabled. In particular:
 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.
 * Multi type views are completely transparent to storage policies.
 * Single type views for stable storage types offer the same interface of multi
 * Single type views for stable storage types offer the same interface of multi
   type views. For example, only `size_hint` is available.
   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>
     template<typename... Exclude, typename... Get, typename... Owned>
     struct group_handler<exclude_t<Exclude...>, get_t<Get...>, 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{};
         std::conditional_t<sizeof...(Owned) == 0, basic_common_type, std::size_t> current{};
 
 
         template<typename Component>
         template<typename Component>
         void maybe_valid_if(basic_registry &owner, const Entity entt) {
         void maybe_valid_if(basic_registry &owner, const Entity entt) {
             [[maybe_unused]] const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...);
             [[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)) && ...)
             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)) && ...)
                                   && ((std::is_same_v<Component, Get> || owner.assure<Get>().contains(entt)) && ...)
@@ -209,10 +210,7 @@ class basic_registry {
             if constexpr(sizeof...(Owned) == 0) {
             if constexpr(sizeof...(Owned) == 0) {
                 current.remove(entt);
                 current.remove(entt);
             } else {
             } 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;
                     const auto pos = --current;
                     (std::get<storage_type<Owned> &>(cpools).swap_elements(std::get<storage_type<Owned> &>(cpools).data()[pos], entt), ...);
                     (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;
         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.
      * @brief Returns the next slot available for insertion.
      * @return 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());
     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) {
 TEST(SparseSet, SwapEntity) {
     using traits_type = entt::entt_traits<entt::entity>;
     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());
     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) {
 TEST(Storage, ShrinkToFit) {
     entt::storage<int> pool;
     entt::storage<int> pool;