瀏覽代碼

storage: uniform interface to simplify mixin implementation

Michele Caini 3 年之前
父節點
當前提交
6e4946b682
共有 6 個文件被更改,包括 78 次插入94 次删除
  1. 0 1
      TODO
  2. 48 63
      src/entt/entity/mixin.hpp
  3. 3 3
      src/entt/entity/registry.hpp
  4. 6 6
      src/entt/entity/storage.hpp
  5. 3 3
      test/entt/entity/sigh_mixin.cpp
  6. 18 18
      test/entt/entity/storage_entity.cpp

+ 0 - 1
TODO

@@ -15,7 +15,6 @@ TODO (high prio):
 * check natvis files (periodically :)
 * remove the static storage from the const assure in the registry
 * pop_if to improve further destroying entities (drastically)
-* improve sigh mixin for entity storage (split basic + entt/entt spec)
 * doc: exclude only views, storage entity (and diff between iterator and each based iteration), bump entities, signals on entity creation/destruction
 * registry::destroy avoid pack if entity storage iterators already
 * registry: replace destroy with a drop-all method that doesn't care about validity

+ 48 - 63
src/entt/entity/mixin.hpp

@@ -192,18 +192,46 @@ public:
     }
 
     /**
-     * @brief Assigns entities to a storage.
-     * @tparam Args Types of arguments to use to construct the object.
-     * @param entt A valid identifier.
-     * @param args Parameters to use to initialize the object.
-     * @return A reference to the newly created object.
+     * @brief Emplace elements into a storage.
+     *
+     * The behavior of this operation depends on the underlying storage type
+     * (for example, components vs entities).<br/>
+     * Refer to the specific documentation for more details.
+     *
+     * @return A return value as returned by the underlying storage.
      */
-    template<typename... Args>
-    decltype(auto) emplace(const entity_type entt, Args &&...args) {
+    auto emplace() {
         ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
-        Type::emplace(entt, std::forward<Args>(args)...);
+        const auto entt = Type::emplace();
         construction.publish(*owner, entt);
-        return this->get(entt);
+        return entt;
+    }
+
+    /**
+     * @brief Emplace elements into a storage.
+     *
+     * The behavior of this operation depends on the underlying storage type
+     * (for example, components vs entities).<br/>
+     * Refer to the specific documentation for more details.
+     *
+     * @tparam Args Types of arguments to forward to the underlying storage.
+     * @param hint A valid identifier.
+     * @param args Parameters to forward to the underlying storage.
+     * @return A return value as returned by the underlying storage.
+     */
+    template<typename... Args>
+    decltype(auto) emplace(const entity_type hint, Args &&...args) {
+        ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
+
+        if constexpr(std::is_same_v<typename Type::value_type, typename Type::entity_type>) {
+            const auto entt = Type::emplace(hint, std::forward<Args>(args)...);
+            construction.publish(*owner, entt);
+            return entt;
+        } else {
+            Type::emplace(hint, std::forward<Args>(args)...);
+            construction.publish(*owner, hint);
+            return this->get(hint);
+        }
     }
 
     /**
@@ -222,14 +250,17 @@ public:
     }
 
     /**
-     * @brief Assigns entities to a storage.
-     * @tparam It Type of input iterator.
-     * @tparam Args Types of arguments to use to construct the objects assigned
-     * to the entities.
-     * @param first An iterator to the first element of the range of entities.
-     * @param last An iterator past the last element of the range of entities.
-     * @param args Parameters to use to initialize the objects assigned to the
-     * entities.
+     * @brief Emplace elements into a storage.
+     *
+     * The behavior of this operation depends on the underlying storage type
+     * (for example, components vs entities).<br/>
+     * Refer to the specific documentation for more details.
+     *
+     * @tparam It Iterator type (as required by the underlying storage type).
+     * @tparam Args Types of arguments to forward to the underlying storage.
+     * @param first An iterator to the first element of the range.
+     * @param last An iterator past the last element of the range.
+     * @param args Parameters to use to forward to the underlying storage.
      */
     template<typename It, typename... Args>
     void insert(It first, It last, Args &&...args) {
@@ -244,52 +275,6 @@ public:
         }
     }
 
-    /**
-     * @brief Creates a new identifier or recycles a destroyed one.
-     * @return A valid identifier.
-     */
-    entity_type spawn() {
-        ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
-        const auto entt = Type::spawn();
-        construction.publish(*owner, entt);
-        return entt;
-    }
-
-    /**
-     * @brief Creates a new identifier or recycles a destroyed one.
-     *
-     * If the requested identifier isn't in use, the suggested one is used.
-     * Otherwise, a new identifier is returned.
-     *
-     * @param hint Required identifier.
-     * @return A valid identifier.
-     */
-    entity_type spawn(const entity_type hint) {
-        ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
-        const auto entt = Type::spawn(hint);
-        construction.publish(*owner, entt);
-        return entt;
-    }
-
-    /**
-     * @brief Assigns each element in a range an identifier.
-     * @tparam It Type of mutable forward iterator.
-     * @param first An iterator to the first element of the range to generate.
-     * @param last An iterator past the last element of the range to generate.
-     */
-    template<typename It>
-    void spawn(It first, It last) {
-        Type::spawn(first, last);
-
-        if(!construction.empty()) {
-            ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
-
-            for(; first != last; ++first) {
-                construction.publish(*owner, *first);
-            }
-        }
-    }
-
     /**
      * @brief Forwards variables to derived classes, if any.
      * @param value A variable wrapped in an opaque container.

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

@@ -588,7 +588,7 @@ public:
      * @return A valid identifier.
      */
     [[nodiscard]] entity_type create() {
-        return shortcut->spawn();
+        return shortcut->emplace();
     }
 
     /**
@@ -601,7 +601,7 @@ public:
      * @return A valid identifier.
      */
     [[nodiscard]] entity_type create(const entity_type hint) {
-        return shortcut->spawn(hint);
+        return shortcut->emplace(hint);
     }
 
     /**
@@ -615,7 +615,7 @@ public:
      */
     template<typename It>
     void create(It first, It last) {
-        shortcut->spawn(std::move(first), std::move(last));
+        shortcut->insert(std::move(first), std::move(last));
     }
 
     /**

+ 6 - 6
src/entt/entity/storage.hpp

@@ -964,7 +964,7 @@ protected:
      * @return Iterator pointing to the emplaced element.
      */
     underlying_iterator try_emplace(const Entity hint, const bool, const void *) override {
-        return base_type::find(spawn(hint));
+        return base_type::find(emplace(hint));
     }
 
 public:
@@ -1068,7 +1068,7 @@ public:
      * @brief Creates a new identifier or recycles a destroyed one.
      * @return A valid identifier.
      */
-    entity_type spawn() {
+    entity_type emplace() {
         if(length == base_type::size()) {
             return *base_type::try_emplace(entity_at(length++), true);
         }
@@ -1085,9 +1085,9 @@ public:
      * @param hint Required identifier.
      * @return A valid identifier.
      */
-    entity_type spawn(const entity_type hint) {
+    entity_type emplace(const entity_type hint) {
         if(hint == null || hint == tombstone) {
-            return spawn();
+            return emplace();
         } else if(const auto curr = local_traits_type::construct(local_traits_type::to_entity(hint), base_type::current(hint)); curr == tombstone) {
             const auto pos = static_cast<size_type>(local_traits_type::to_entity(hint));
 
@@ -1097,7 +1097,7 @@ public:
 
             base_type::swap_at(pos, length++);
         } else if(const auto idx = base_type::index(curr); idx < length) {
-            return spawn();
+            return emplace();
         } else {
             base_type::swap_at(idx, length++);
         }
@@ -1114,7 +1114,7 @@ public:
      * @param last An iterator past the last element of the range to generate.
      */
     template<typename It>
-    void spawn(It first, It last) {
+    void insert(It first, It last) {
         for(const auto sz = base_type::size(); first != last && length != sz; ++first, ++length) {
             *first = base_type::operator[](length);
         }

+ 3 - 3
test/entt/entity/sigh_mixin.cpp

@@ -510,11 +510,11 @@ TEST(SighMixin, StorageEntity) {
     ASSERT_EQ(on_construct.value, 3);
     ASSERT_EQ(on_destroy.value, 3);
 
-    pool.spawn();
-    pool.spawn(entt::entity{0});
+    pool.emplace();
+    pool.emplace(entt::entity{0});
 
     entt::entity entities[1u]{};
-    pool.spawn(entities, entities + 1u);
+    pool.insert(entities, entities + 1u);
 
     ASSERT_EQ(on_construct.value, 6);
     ASSERT_EQ(on_destroy.value, 3);

+ 18 - 18
test/entt/entity/storage_entity.cpp

@@ -45,7 +45,7 @@ TEST(StorageEntity, Functionalities) {
 
 ENTT_DEBUG_TEST(StorageEntityDeathTest, Get) {
     entt::storage<entt::entity> pool;
-    pool.spawn(entt::entity{99});
+    pool.emplace(entt::entity{99});
 
     ASSERT_DEATH(pool.get(entt::entity{3}), "");
     ASSERT_DEATH([[maybe_unused]] auto tup = pool.get_as_tuple(entt::entity{3}), "");
@@ -187,18 +187,18 @@ TEST(StorageEntity, Push) {
     ASSERT_EQ(*pool.push(entt::null), entt::entity{7});
 }
 
-TEST(StorageEntity, Spawn) {
+TEST(StorageEntity, Emplace) {
     using traits_type = entt::entt_traits<entt::entity>;
 
     entt::storage<entt::entity> pool;
     entt::entity entities[2u]{};
 
-    ASSERT_EQ(pool.spawn(), entt::entity{0});
-    ASSERT_EQ(pool.spawn(entt::null), entt::entity{1});
-    ASSERT_EQ(pool.spawn(entt::tombstone), entt::entity{2});
-    ASSERT_EQ(pool.spawn(entt::entity{0}), entt::entity{3});
-    ASSERT_EQ(pool.spawn(traits_type::construct(1, 1)), entt::entity{4});
-    ASSERT_EQ(pool.spawn(traits_type::construct(6, 3)), traits_type::construct(6, 3));
+    ASSERT_EQ(pool.emplace(), entt::entity{0});
+    ASSERT_EQ(pool.emplace(entt::null), entt::entity{1});
+    ASSERT_EQ(pool.emplace(entt::tombstone), entt::entity{2});
+    ASSERT_EQ(pool.emplace(entt::entity{0}), entt::entity{3});
+    ASSERT_EQ(pool.emplace(traits_type::construct(1, 1)), entt::entity{4});
+    ASSERT_EQ(pool.emplace(traits_type::construct(6, 3)), traits_type::construct(6, 3));
 
     ASSERT_LT(pool.index(entt::entity{0}), pool.in_use());
     ASSERT_LT(pool.index(entt::entity{1}), pool.in_use());
@@ -208,15 +208,15 @@ TEST(StorageEntity, Spawn) {
     ASSERT_GE(pool.index(entt::entity{5}), pool.in_use());
     ASSERT_LT(pool.index(traits_type::construct(6, 3)), pool.in_use());
 
-    ASSERT_EQ(pool.spawn(traits_type::construct(5, 42)), traits_type::construct(5, 42));
-    ASSERT_EQ(pool.spawn(traits_type::construct(5, 43)), entt::entity{7});
+    ASSERT_EQ(pool.emplace(traits_type::construct(5, 42)), traits_type::construct(5, 42));
+    ASSERT_EQ(pool.emplace(traits_type::construct(5, 43)), entt::entity{7});
 
     pool.erase(entt::entity{2});
 
-    ASSERT_EQ(pool.spawn(), traits_type::construct(2, 1));
+    ASSERT_EQ(pool.emplace(), traits_type::construct(2, 1));
 
     pool.erase(traits_type::construct(2, 1));
-    pool.spawn(entities, entities + 2u);
+    pool.insert(entities, entities + 2u);
 
     ASSERT_EQ(entities[0u], traits_type::construct(2, 2));
     ASSERT_EQ(entities[1u], entt::entity{8});
@@ -256,9 +256,9 @@ TEST(StorageEntity, Iterable) {
 
     entt::storage<entt::entity> pool;
 
-    pool.spawn(entt::entity{1});
-    pool.spawn(entt::entity{3});
-    pool.spawn(entt::entity{42});
+    pool.emplace(entt::entity{1});
+    pool.emplace(entt::entity{3});
+    pool.emplace(entt::entity{42});
 
     pool.erase(entt::entity{3});
 
@@ -300,9 +300,9 @@ TEST(StorageEntity, ConstIterable) {
 
     entt::storage<entt::entity> pool;
 
-    pool.spawn(entt::entity{1});
-    pool.spawn(entt::entity{3});
-    pool.spawn(entt::entity{42});
+    pool.emplace(entt::entity{1});
+    pool.emplace(entt::entity{3});
+    pool.emplace(entt::entity{42});
 
     pool.erase(entt::entity{3});