Răsfoiți Sursa

storage: add get/get_as_tuple to entity storage to make it suitable for use with views

Michele Caini 3 ani în urmă
părinte
comite
c0762a6a5a
3 a modificat fișierele cu 65 adăugiri și 19 ștergeri
  1. 1 2
      TODO
  2. 45 17
      src/entt/entity/storage.hpp
  3. 19 0
      test/entt/entity/storage_entity.cpp

+ 1 - 2
TODO

@@ -20,9 +20,8 @@ TODO (high prio):
 * improve sigh mixin for entity storage (split basic + entt/entt spec)
 * doc: exclude only views, storage entity, bump entities
 * deprecate/remove registry reserve, capacity, empty, data, destroyed, release and so on
-* prepare to turn sparse set begin/end into virtual functions
 * refine views and groups to use scoped iterators from entity storage and the like
-* use sparse_set free_list to replace entity storage length and return narrow iterators
+* use entity as value_type for entity storage, define begin/end as scoped iterators
 * test exclude-only views
 
 WIP:

+ 45 - 17
src/entt/entity/storage.hpp

@@ -949,7 +949,7 @@ protected:
             if(const auto pos = base_type::index(*first); pos < length) {
                 base_type::bump(local_traits_type::next(*first));
 
-                if (pos != --length) {
+                if(pos != --length) {
                     base_type::swap_at(pos, length);
                 }
             }
@@ -1031,6 +1031,34 @@ public:
         return *this;
     }
 
+    /**
+     * @brief Returns the object assigned to an entity, that is `void`.
+     *
+     * @warning
+     * Attempting to use an entity that doesn't belong to the storage results in
+     * undefined behavior.
+     *
+     * @param entt A valid identifier.
+     */
+    void get([[maybe_unused]] const entity_type entt) const noexcept {
+        ENTT_ASSERT(base_type::index(entt) < length, "The requested entity is not a live one");
+    }
+
+    /**
+     * @brief Returns an empty tuple.
+     *
+     * @warning
+     * Attempting to use an entity that doesn't belong to the storage results in
+     * undefined behavior.
+     *
+     * @param entt A valid identifier.
+     * @return Returns an empty tuple.
+     */
+    [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const noexcept {
+        ENTT_ASSERT(base_type::index(entt) < length, "The requested entity is not a live one");
+        return std::tuple{};
+    }
+
     /**
      * @brief Exchanges the contents with those of a given storage.
      * @param other Storage to exchange the content with.
@@ -1121,22 +1149,6 @@ public:
         return (length - len);
     }
 
-    /**
-     * @brief Returns an iterable object to use to _visit_ a storage.
-     *
-     * The iterable object returns a tuple that contains the current entity.
-     *
-     * @return An iterable object to use to _visit_ the storage.
-     */
-    [[nodiscard]] iterable each() noexcept {
-        return {internal::extended_storage_iterator{base_type::end() - length}, internal::extended_storage_iterator{base_type::end()}};
-    }
-
-    /*! @copydoc each */
-    [[nodiscard]] const_iterable each() const noexcept {
-        return {internal::extended_storage_iterator{base_type::cend() - length}, internal::extended_storage_iterator{base_type::cend()}};
-    }
-
     /**
      * @brief Returns the number of elements considered still in use.
      * @return The number of elements considered still in use.
@@ -1154,6 +1166,22 @@ public:
         length = len;
     }
 
+    /**
+     * @brief Returns an iterable object to use to _visit_ a storage.
+     *
+     * The iterable object returns a tuple that contains the current entity.
+     *
+     * @return An iterable object to use to _visit_ the storage.
+     */
+    [[nodiscard]] iterable each() noexcept {
+        return {internal::extended_storage_iterator{base_type::end() - length}, internal::extended_storage_iterator{base_type::end()}};
+    }
+
+    /*! @copydoc each */
+    [[nodiscard]] const_iterable each() const noexcept {
+        return {internal::extended_storage_iterator{base_type::cend() - length}, internal::extended_storage_iterator{base_type::cend()}};
+    }
+
 private:
     size_type length;
 };

+ 19 - 0
test/entt/entity/storage_entity.cpp

@@ -33,6 +33,9 @@ TEST(StorageEntity, Functionalities) {
     ASSERT_EQ(pool.size(), 2u);
     ASSERT_EQ(pool.in_use(), 1u);
 
+    ASSERT_NO_THROW(pool.get(entities[0u]));
+    ASSERT_EQ(pool.get_as_tuple(entities[0u]), std::tuple<>{});
+
     pool.erase(entities[0u]);
 
     ASSERT_FALSE(pool.empty());
@@ -40,6 +43,22 @@ TEST(StorageEntity, Functionalities) {
     ASSERT_EQ(pool.in_use(), 0u);
 }
 
+ENTT_DEBUG_TEST(StorageEntityDeathTest, Get) {
+    entt::storage<entt::entity> pool;
+    pool.spawn(entt::entity{99});
+
+    ASSERT_DEATH(pool.get(entt::entity{3}), "");
+    ASSERT_DEATH([[maybe_unused]] auto tup = pool.get_as_tuple(entt::entity{3}), "");
+
+    ASSERT_NO_THROW(pool.get(entt::entity{99}));
+    ASSERT_NO_THROW([[maybe_unused]] auto tup = pool.get_as_tuple(entt::entity{99}));
+
+    pool.erase(entt::entity{99});
+
+    ASSERT_DEATH(pool.get(entt::entity{99}), "");
+    ASSERT_DEATH([[maybe_unused]] auto tup = pool.get_as_tuple(entt::entity{99}), "");
+}
+
 TEST(StorageEntity, Move) {
     using traits_type = entt::entt_traits<entt::entity>;