瀏覽代碼

registry/group: pool<T>::super is no longer required

Michele Caini 5 年之前
父節點
當前提交
7e624159ee
共有 3 個文件被更改,包括 151 次插入151 次删除
  1. 2 14
      src/entt/entity/group.hpp
  2. 143 131
      src/entt/entity/registry.hpp
  3. 6 6
      test/entt/entity/registry.cpp

+ 2 - 14
src/entt/entity/group.hpp

@@ -491,10 +491,9 @@ class basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned...> {
     template<typename Component>
     using component_iterator = decltype(std::declval<pool_type<Component>>().begin());
 
-    basic_group(const std::size_t &ref, const std::size_t &extent, pool_type<Owned> &... opool, pool_type<Get> &... gpool) ENTT_NOEXCEPT
+    basic_group(const std::size_t &extent, pool_type<Owned> &... opool, pool_type<Get> &... gpool) ENTT_NOEXCEPT
         : pools{&opool..., &gpool...},
-          length{&extent},
-          super{&ref}
+          length{&extent}
     {}
 
     template<typename Func, typename... Strong, typename... Weak>
@@ -760,15 +759,6 @@ public:
         traverse(std::move(func), owned_type_list{}, get_type_list{});
     }
 
-    /**
-     * @brief Checks whether the group can be sorted.
-     * @return True if the group can be sorted, false otherwise.
-     */
-    [[nodiscard]] bool sortable() const ENTT_NOEXCEPT {
-        constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
-        return *super == size;
-    }
-
     /**
      * @brief Sort a group according to the given comparison function.
      *
@@ -808,7 +798,6 @@ public:
      */
     template<typename... Component, typename Compare, typename Sort = std_sort, typename... Args>
     void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
-        ENTT_ASSERT(sortable());
         auto *cpool = std::get<0>(pools);
 
         if constexpr(sizeof...(Component) == 0) {
@@ -836,7 +825,6 @@ public:
 private:
     const std::tuple<pool_type<Owned> *..., pool_type<Get> *...> pools;
     const size_type *length;
-    const size_type *super;
 };
 
 

+ 143 - 131
src/entt/entity/registry.hpp

@@ -46,7 +46,6 @@ class basic_registry {
     template<typename Component>
     struct pool_handler final: storage<Entity, Component> {
         static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Invalid component type");
-        std::size_t super{};
 
         [[nodiscard]] auto on_construct() ENTT_NOEXCEPT {
             return sink{construction};
@@ -1161,101 +1160,6 @@ public:
         return assure<Component>().on_destroy();
     }
 
-    /**
-     * @brief Sorts the pool of entities for the given component.
-     *
-     * The order of the elements in a pool is highly affected by assignments
-     * of components to entities and deletions. Components are arranged to
-     * maximize the performance during iterations and users should not make any
-     * assumption on the order.<br/>
-     * This function can be used to impose an order to the elements in the pool
-     * of the given component. The order is kept valid until a component of the
-     * given type is assigned or removed from an entity.
-     *
-     * The comparison function object must return `true` if the first element
-     * is _less_ than the second one, `false` otherwise. The signature of the
-     * comparison function should be equivalent to one of the following:
-     *
-     * @code{.cpp}
-     * bool(const Entity, const Entity);
-     * bool(const Component &, const Component &);
-     * @endcode
-     *
-     * Moreover, the comparison function object shall induce a
-     * _strict weak ordering_ on the values.
-     *
-     * The sort function oject must offer a member function template
-     * `operator()` that accepts three arguments:
-     *
-     * * An iterator to the first element of the range to sort.
-     * * An iterator past the last element of the range to sort.
-     * * A comparison function to use to compare the elements.
-     *
-     * The comparison funtion object received by the sort function object hasn't
-     * necessarily the type of the one passed along with the other parameters to
-     * this member function.
-     *
-     * @warning
-     * Pools of components owned by a group cannot be sorted.<br/>
-     * An assertion will abort the execution at runtime in debug mode in case
-     * the pool is owned by a group.
-     *
-     * @tparam Component Type of components to sort.
-     * @tparam Compare Type of comparison function object.
-     * @tparam Sort Type of sort function object.
-     * @tparam Args Types of arguments to forward to the sort function object.
-     * @param compare A valid comparison function object.
-     * @param algo A valid sort function object.
-     * @param args Arguments to forward to the sort function object, if any.
-     */
-    template<typename Component, typename Compare, typename Sort = std_sort, typename... Args>
-    void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
-        ENTT_ASSERT(sortable<Component>());
-        auto &cpool = assure<Component>();
-        cpool.sort(cpool.begin(), cpool.end(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
-    }
-
-    /**
-     * @brief Sorts two pools of components in the same way.
-     *
-     * The order of the elements in a pool is highly affected by assignments
-     * of components to entities and deletions. Components are arranged to
-     * maximize the performance during iterations and users should not make any
-     * assumption on the order.
-     *
-     * It happens that different pools of components must be sorted the same way
-     * because of runtime and/or performance constraints. This function can be
-     * used to order a pool of components according to the order between the
-     * entities in another pool of components.
-     *
-     * @b How @b it @b works
-     *
-     * Being `A` and `B` the two sets where `B` is the master (the one the order
-     * of which rules) and `A` is the slave (the one to sort), after a call to
-     * this function an iterator for `A` will return the entities according to
-     * the following rules:
-     *
-     * * All the entities in `A` that are also in `B` are returned first
-     *   according to the order they have in `B`.
-     * * All the entities in `A` that are not in `B` are returned in no
-     *   particular order after all the other entities.
-     *
-     * Any subsequent change to `B` won't affect the order in `A`.
-     *
-     * @warning
-     * Pools of components owned by a group cannot be sorted.<br/>
-     * An assertion will abort the execution at runtime in debug mode in case
-     * the pool is owned by a group.
-     *
-     * @tparam To Type of components to sort.
-     * @tparam From Type of components to use to sort.
-     */
-    template<typename To, typename From>
-    void sort() {
-        ENTT_ASSERT(sortable<To>());
-        assure<To>().respect(assure<From>());
-    }
-
     /**
      * @brief Returns a view for the given components.
      *
@@ -1302,14 +1206,35 @@ public:
     }
 
     /**
-     * @brief Checks whether the given components belong to any group.
-     * @tparam Component Types of components in which one is interested.
-     * @return True if the pools of the given components are sortable, false
-     * otherwise.
+     * @brief Returns a runtime view for the given components.
+     *
+     * This kind of objects are created on the fly and share with the registry
+     * its internal data structures.<br/>
+     * Users should throw away the view after use. Fortunately, creating and
+     * destroying a runtime view is an incredibly cheap operation because they
+     * do not require any type of initialization.<br/>
+     * As a rule of thumb, storing a view should never be an option.
+     *
+     * Runtime views are to be used when users want to construct a view from
+     * some external inputs and don't know at compile-time what are the required
+     * components.<br/>
+     * This is particularly well suited to plugin systems and mods in general.
+     *
+     * @tparam It Type of input iterator.
+     * @param first An iterator to the first element of the range of components.
+     * @param last An iterator past the last element of the range of components.
+     * @return A newly created runtime view.
      */
-    template<typename... Component>
-    [[nodiscard]] bool sortable() const {
-        return std::none_of(groups.cbegin(), groups.cend(), [](auto &&gdata) { return (gdata.owned(type_info<std::decay_t<Component>>::id()) || ...); });
+    template<typename It>
+    [[nodiscard]] entt::basic_runtime_view<Entity> runtime_view(It first, It last) const {
+        std::vector<const sparse_set<Entity> *> selected(std::distance(first, last));
+
+        std::transform(first, last, selected.begin(), [this](const auto ctype) {
+            const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.pool && pdata.type_id == ctype; });
+            return it == pools.cend() ? nullptr : it->pool.get();
+        });
+
+        return { std::move(selected) };
     }
 
     /**
@@ -1384,7 +1309,7 @@ public:
                 }));
 
                 const auto next = std::find_if_not(groups.cbegin(), groups.cend(), [size](const auto &gdata) {
-                    return !(0u + ... + gdata.owned(type_info<std::decay_t<Owned>>::id())) || (size > (gdata.size));
+                    return !(0u + ... + gdata.owned(type_info<std::decay_t<Owned>>::id())) || (size > gdata.size);
                 });
 
                 const auto prev = std::find_if(std::make_reverse_iterator(next), groups.crend(), [](const auto &gdata) {
@@ -1396,8 +1321,6 @@ public:
                 groups.insert(next, std::move(candidate));
             }
 
-            ((std::get<pool_handler<std::decay_t<Owned>> &>(cpools).super = std::max(std::get<pool_handler<std::decay_t<Owned>> &>(cpools).super, size)), ...);
-
             (on_construct<std::decay_t<Owned>>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<std::decay_t<Owned>>>(*handler), ...);
             (on_construct<std::decay_t<Get>>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<std::decay_t<Get>>>(*handler), ...);
             (on_destroy<Exclude>().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if<Exclude>>(*handler), ...);
@@ -1421,7 +1344,7 @@ public:
         if constexpr(sizeof...(Owned) == 0) {
             return { handler->current, std::get<pool_handler<std::decay_t<Get>> &>(cpools)... };
         } else {
-            return { std::get<0>(cpools).super, handler->current, std::get<pool_handler<std::decay_t<Owned>> &>(cpools)... , std::get<pool_handler<std::decay_t<Get>> &>(cpools)... };
+            return { handler->current, std::get<pool_handler<std::decay_t<Owned>> &>(cpools)... , std::get<pool_handler<std::decay_t<Get>> &>(cpools)... };
         }
     }
 
@@ -1471,35 +1394,124 @@ public:
     }
 
     /**
-     * @brief Returns a runtime view for the given components.
+     * @brief Checks whether the given components belong to any group.
+     * @tparam Component Types of components in which one is interested.
+     * @return True if the pools of the given components are sortable, false
+     * otherwise.
+     */
+    template<typename... Component>
+    [[nodiscard]] bool sortable() const {
+        return std::none_of(groups.cbegin(), groups.cend(), [](auto &&gdata) { return (gdata.owned(type_info<std::decay_t<Component>>::id()) || ...); });
+    }
+
+    /**
+     * @brief Checks whether a group can be sorted.
+     * @tparam Owned Types of components owned by the group.
+     * @tparam Get Types of components observed by the group.
+     * @tparam Exclude Types of components used to filter the group.
+     * @return True if the group can be sorted, false otherwise.
+     */
+    template<typename... Owned, typename... Get, typename... Exclude>
+    [[nodiscard]] bool sortable(const entt::basic_group<Entity, exclude_t<Exclude...>, get_t<Get...>, Owned...> &) ENTT_NOEXCEPT {
+        constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude);
+        return std::find_if(groups.cbegin(), groups.cend(), [size](const auto &gdata) {
+            return (0u + ... + gdata.owned(type_info<std::decay_t<Owned>>::id())) && (size < gdata.size);
+        }) == groups.cend();
+    }
+
+    /**
+     * @brief Sorts the pool of entities for the given component.
      *
-     * This kind of objects are created on the fly and share with the registry
-     * its internal data structures.<br/>
-     * Users should throw away the view after use. Fortunately, creating and
-     * destroying a runtime view is an incredibly cheap operation because they
-     * do not require any type of initialization.<br/>
-     * As a rule of thumb, storing a view should never be an option.
+     * The order of the elements in a pool is highly affected by assignments
+     * of components to entities and deletions. Components are arranged to
+     * maximize the performance during iterations and users should not make any
+     * assumption on the order.<br/>
+     * This function can be used to impose an order to the elements in the pool
+     * of the given component. The order is kept valid until a component of the
+     * given type is assigned or removed from an entity.
      *
-     * Runtime views are to be used when users want to construct a view from
-     * some external inputs and don't know at compile-time what are the required
-     * components.<br/>
-     * This is particularly well suited to plugin systems and mods in general.
+     * The comparison function object must return `true` if the first element
+     * is _less_ than the second one, `false` otherwise. The signature of the
+     * comparison function should be equivalent to one of the following:
      *
-     * @tparam It Type of input iterator.
-     * @param first An iterator to the first element of the range of components.
-     * @param last An iterator past the last element of the range of components.
-     * @return A newly created runtime view.
+     * @code{.cpp}
+     * bool(const Entity, const Entity);
+     * bool(const Component &, const Component &);
+     * @endcode
+     *
+     * Moreover, the comparison function object shall induce a
+     * _strict weak ordering_ on the values.
+     *
+     * The sort function oject must offer a member function template
+     * `operator()` that accepts three arguments:
+     *
+     * * An iterator to the first element of the range to sort.
+     * * An iterator past the last element of the range to sort.
+     * * A comparison function to use to compare the elements.
+     *
+     * The comparison funtion object received by the sort function object hasn't
+     * necessarily the type of the one passed along with the other parameters to
+     * this member function.
+     *
+     * @warning
+     * Pools of components owned by a group cannot be sorted.<br/>
+     * An assertion will abort the execution at runtime in debug mode in case
+     * the pool is owned by a group.
+     *
+     * @tparam Component Type of components to sort.
+     * @tparam Compare Type of comparison function object.
+     * @tparam Sort Type of sort function object.
+     * @tparam Args Types of arguments to forward to the sort function object.
+     * @param compare A valid comparison function object.
+     * @param algo A valid sort function object.
+     * @param args Arguments to forward to the sort function object, if any.
      */
-    template<typename It>
-    [[nodiscard]] entt::basic_runtime_view<Entity> runtime_view(It first, It last) const {
-        std::vector<const sparse_set<Entity> *> selected(std::distance(first, last));
-
-        std::transform(first, last, selected.begin(), [this](const auto ctype) {
-            const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.pool && pdata.type_id == ctype; });
-            return it == pools.cend() ? nullptr : it->pool.get();
-        });
+    template<typename Component, typename Compare, typename Sort = std_sort, typename... Args>
+    void sort(Compare compare, Sort algo = Sort{}, Args &&... args) {
+        ENTT_ASSERT(sortable<Component>());
+        auto &cpool = assure<Component>();
+        cpool.sort(cpool.begin(), cpool.end(), std::move(compare), std::move(algo), std::forward<Args>(args)...);
+    }
 
-        return { std::move(selected) };
+    /**
+     * @brief Sorts two pools of components in the same way.
+     *
+     * The order of the elements in a pool is highly affected by assignments
+     * of components to entities and deletions. Components are arranged to
+     * maximize the performance during iterations and users should not make any
+     * assumption on the order.
+     *
+     * It happens that different pools of components must be sorted the same way
+     * because of runtime and/or performance constraints. This function can be
+     * used to order a pool of components according to the order between the
+     * entities in another pool of components.
+     *
+     * @b How @b it @b works
+     *
+     * Being `A` and `B` the two sets where `B` is the master (the one the order
+     * of which rules) and `A` is the slave (the one to sort), after a call to
+     * this function an iterator for `A` will return the entities according to
+     * the following rules:
+     *
+     * * All the entities in `A` that are also in `B` are returned first
+     *   according to the order they have in `B`.
+     * * All the entities in `A` that are not in `B` are returned in no
+     *   particular order after all the other entities.
+     *
+     * Any subsequent change to `B` won't affect the order in `A`.
+     *
+     * @warning
+     * Pools of components owned by a group cannot be sorted.<br/>
+     * An assertion will abort the execution at runtime in debug mode in case
+     * the pool is owned by a group.
+     *
+     * @tparam To Type of components to sort.
+     * @tparam From Type of components to use to sort.
+     */
+    template<typename To, typename From>
+    void sort() {
+        ENTT_ASSERT(sortable<To>());
+        assure<To>().respect(assure<From>());
     }
 
     /**

+ 6 - 6
test/entt/entity/registry.cpp

@@ -830,13 +830,13 @@ TEST(Registry, NestedGroups) {
     registry.insert<char>(std::begin(entities), std::end(entities));
     const auto g1 = registry.group<int>(entt::get<char>, entt::exclude<double>);
 
-    ASSERT_TRUE(g1.sortable());
+    ASSERT_TRUE(registry.sortable(g1));
     ASSERT_EQ(g1.size(), 10u);
 
     const auto g2 = registry.group<int>(entt::get<char>);
 
-    ASSERT_TRUE(g1.sortable());
-    ASSERT_FALSE(g2.sortable());
+    ASSERT_TRUE(registry.sortable(g1));
+    ASSERT_FALSE(registry.sortable(g2));
     ASSERT_EQ(g1.size(), 10u);
     ASSERT_EQ(g2.size(), 10u);
 
@@ -864,9 +864,9 @@ TEST(Registry, NestedGroups) {
 
     const auto g3= registry.group<int, float>(entt::get<char>, entt::exclude<double>);
 
-    ASSERT_FALSE(g1.sortable());
-    ASSERT_FALSE(g2.sortable());
-    ASSERT_TRUE(g3.sortable());
+    ASSERT_FALSE(registry.sortable(g1));
+    ASSERT_FALSE(registry.sortable(g2));
+    ASSERT_TRUE(registry.sortable(g3));
 
     ASSERT_EQ(g1.size(), 0u);
     ASSERT_EQ(g2.size(), 5u);