Kaynağa Gözat

entity: fully remove the poly storage support

Michele Caini 4 yıl önce
ebeveyn
işleme
00e7ab1db8

+ 0 - 1
CMakeLists.txt

@@ -146,7 +146,6 @@ if(ENTT_INCLUDE_HEADERS)
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/helper.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/helper.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/observer.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/observer.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/organizer.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/organizer.hpp>
-            $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/poly_storage.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/registry.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/registry.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/runtime_view.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/runtime_view.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/snapshot.hpp>
             $<BUILD_INTERFACE:${EnTT_SOURCE_DIR}/src/entt/entity/snapshot.hpp>

+ 2 - 56
docs/md/entity.md

@@ -31,7 +31,6 @@
     * [In-place delete](#in-place-delete)
     * [In-place delete](#in-place-delete)
     * [Hierarchies and the like](#hierarchies-and-the-like)
     * [Hierarchies and the like](#hierarchies-and-the-like)
   * [Making the most of range-destroy](#making-the-most-of-range-destroy)
   * [Making the most of range-destroy](#making-the-most-of-range-destroy)
-  * [Meet the runtime](#meet-the-runtime)
   * [Snapshot: complete vs continuous](#snapshot-complete-vs-continuous)
   * [Snapshot: complete vs continuous](#snapshot-complete-vs-continuous)
     * [Snapshot loader](#snapshot-loader)
     * [Snapshot loader](#snapshot-loader)
     * [Continuous loader](#continuous-loader)
     * [Continuous loader](#continuous-loader)
@@ -101,8 +100,8 @@ The library provides a default implementation for many things and a mixin model
 that allows users to completely replace or even just enrich the pool dedicated
 that allows users to completely replace or even just enrich the pool dedicated
 to one or more components.<br/>
 to one or more components.<br/>
 The built-in signal support is an example of that: defined as a mixin, it's
 The built-in signal support is an example of that: defined as a mixin, it's
-easily disabled if not needed. Similarly, poly storage is another example of how
-everything is customizable down to the smallest detail.
+easily disabled if not needed. Similarly, the storage class has a specialization
+that shows how everything is customizable down to the smallest detail.
 
 
 ## Pay per use
 ## Pay per use
 
 
@@ -1140,59 +1139,6 @@ to do the above even after writing millions of lines of code.<br/>
 However, it's good to know how to exploit the `destroy` function to get the best
 However, it's good to know how to exploit the `destroy` function to get the best
 out of it.
 out of it.
 
 
-## Meet the runtime
-
-`EnTT` takes full advantage of what the language offers at compile-time.<br/>
-However, by combining these feature with a tool for static polymorphism, it's
-also possible to have opaque proxies to work with _type-less_ pools at runtime.
-
-These objects are returned by the `storage` member function, which accepts a
-`type_info` object as an argument rather than a compile-time type (the same
-returned by the `visit` member function):
-
-```cpp
-auto storage = registry.storage(info);
-```
-
-By default and to stay true with the philosophy of the library, the API of a
-proxy is minimal and doesn't allow users to do much.<br/>
-However, it's also completely customizable in a generic way and with the
-possibility of defining specific behaviors for given types.
-
-This section won't go into detail on how to define a poly storage to get all the
-possible functionalities out of it. `EnTT` already contains enough snippets to
-get inspiration from, both in the test suite and in the `example` folder.<br/>
-In short, users will have to define their own _concepts_ (see the `entt::poly`
-documentation for this) and register them via the `poly_storage_traits` class
-template, which has been designed as sfinae-friendly for the purpose.
-
-Once the concept that a poly storage must adhere to has been properly defined,
-copying an entity will be as easy as:
-
-```cpp
-registry.visit(entity, [&](const auto info) {
-    auto &&storage = registry.storage(info);
-    storage->emplace(registry, other, storage->get(entity));
-});
-```
-
-Where `other` is the entity to which the elements should be replicated.<br/>
-Similarly, copying entire pools between different registries can look like this:
-
-```cpp
-registry.visit([&](const auto info) {
-    registry.storage(info)->copy_to(other);
-});
-```
-
-Where this time `other` represents the destination registry.
-
-So, all in all, `EnTT` shifts the complexity to the one-time definition of a
-_concept_ that reflects the user's needs, and then leaves room for ease of use
-within the codebase.<br/>
-The possibility of extreme customization is the icing on the cake in this sense,
-allowing users to design this tool around their own requirements.
-
 ## Snapshot: complete vs continuous
 ## Snapshot: complete vs continuous
 
 
 The `registry` class offers basic support to serialization.<br/>
 The `registry` class offers basic support to serialization.<br/>

+ 0 - 54
src/entt/entity/poly_storage.hpp

@@ -1,54 +0,0 @@
-#ifndef ENTT_ENTITY_POLY_STORAGE_HPP
-#define ENTT_ENTITY_POLY_STORAGE_HPP
-
-#include <cstddef>
-#include <tuple>
-#include "../core/type_info.hpp"
-#include "../core/type_traits.hpp"
-#include "../poly/poly.hpp"
-#include "fwd.hpp"
-
-namespace entt {
-
-/**
- * @brief Basic poly storage implementation.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
-template<typename Entity>
-struct Storage: type_list<const type_info &() const ENTT_NOEXCEPT> {
-    /**
-     * @brief Concept definition.
-     * @tparam Base Opaque base class from which to inherit.
-     */
-    template<typename Base>
-    struct type: Base {
-        /**
-         * @brief Returns a type info for the contained objects.
-         * @return The type info for the contained objects.
-         */
-        const type_info &value_type() const ENTT_NOEXCEPT {
-            return poly_call<0>(*this);
-        }
-    };
-
-    /**
-     * @brief Concept implementation.
-     * @tparam Type Type for which to generate an implementation.
-     */
-    template<typename Type>
-    using impl = value_list<&type_id<typename Type::value_type>>;
-};
-
-/**
- * @brief Defines the poly storage type associate with a given entity type.
- * @tparam Entity A valid entity type (see entt_traits for more details).
- */
-template<typename Entity, typename = void>
-struct poly_storage_traits {
-    /*! @brief Poly storage type for the given entity type. */
-    using storage_type = poly<Storage<Entity>>;
-};
-
-} // namespace entt
-
-#endif

+ 23 - 45
src/entt/entity/registry.hpp

@@ -21,7 +21,6 @@
 #include "entity.hpp"
 #include "entity.hpp"
 #include "fwd.hpp"
 #include "fwd.hpp"
 #include "group.hpp"
 #include "group.hpp"
-#include "poly_storage.hpp"
 #include "runtime_view.hpp"
 #include "runtime_view.hpp"
 #include "sparse_set.hpp"
 #include "sparse_set.hpp"
 #include "storage.hpp"
 #include "storage.hpp"
@@ -43,15 +42,14 @@ namespace entt {
 template<typename Entity>
 template<typename Entity>
 class basic_registry {
 class basic_registry {
     using entity_traits = entt_traits<Entity>;
     using entity_traits = entt_traits<Entity>;
-    using poly_storage_type = typename poly_storage_traits<Entity>::storage_type;
     using basic_common_type = basic_sparse_set<Entity>;
     using basic_common_type = basic_sparse_set<Entity>;
 
 
     template<typename Component>
     template<typename Component>
     using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
     using storage_type = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Component>>::storage_type, Component>;
 
 
     struct pool_data {
     struct pool_data {
-        poly_storage_type poly;
         std::unique_ptr<basic_common_type> pool{};
         std::unique_ptr<basic_common_type> pool{};
+        const entt::type_info *info{};
     };
     };
 
 
     template<typename...>
     template<typename...>
@@ -106,16 +104,15 @@ class basic_registry {
     template<typename Component>
     template<typename Component>
     [[nodiscard]] storage_type<Component> *assure() const {
     [[nodiscard]] storage_type<Component> *assure() const {
         static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Non-decayed types not allowed");
         static_assert(std::is_same_v<Component, std::decay_t<Component>>, "Non-decayed types not allowed");
+        auto &&pdata = pools[type_id<Component>().hash()];
 
 
-        if(auto &&pdata = pools[type_id<Component>().hash()]; !pdata.pool) {
-            auto *cpool = new storage_type<Component>{};
-            pdata.pool.reset(cpool);
+        if(!pdata.pool) {
+            pdata.pool.reset(new storage_type<Component>{});
             pdata.pool->context(forward_as_any(const_cast<basic_registry &>(*this)));
             pdata.pool->context(forward_as_any(const_cast<basic_registry &>(*this)));
-            pdata.poly.template emplace<storage_type<Component> &>(*static_cast<storage_type<Component> *>(pdata.pool.get()));
-            return cpool;
-        } else {
-            return static_cast<storage_type<Component> *>(pdata.pool.get());
+            pdata.info = &type_id<Component>();
         }
         }
+
+        return static_cast<storage_type<Component> *>(pdata.pool.get());
     }
     }
 
 
     template<typename Component>
     template<typename Component>
@@ -151,8 +148,6 @@ public:
     using version_type = typename entity_traits::version_type;
     using version_type = typename entity_traits::version_type;
     /*! @brief Unsigned integer type. */
     /*! @brief Unsigned integer type. */
     using size_type = std::size_t;
     using size_type = std::size_t;
-    /*! @brief Poly storage type. */
-    using poly_storage = typename poly_storage_traits<Entity>::storage_type;
 
 
     /*! @brief Default constructor. */
     /*! @brief Default constructor. */
     basic_registry() = default;
     basic_registry() = default;
@@ -201,23 +196,6 @@ public:
         static_cast<void>(assure<Component>());
         static_cast<void>(assure<Component>());
     }
     }
 
 
-    /**
-     * @brief Returns a poly storage for a given type.
-     * @param info The type for which to return a poly storage.
-     * @return A valid poly storage if a pool for the given type exists, an
-     * empty and thus invalid element otherwise.
-     */
-    poly_storage &storage(const type_info &info) {
-        ENTT_ASSERT(pools[info.hash()].poly, "Storage not available");
-        return pools[info.hash()].poly;
-    }
-
-    /*! @copydoc storage */
-    const poly_storage &storage(const type_info &info) const {
-        ENTT_ASSERT(pools[info.hash()].poly, "Storage not available");
-        return pools[info.hash()].poly;
-    }
-
     /**
     /**
      * @brief Returns the number of existing components of the given type.
      * @brief Returns the number of existing components of the given type.
      * @tparam Component Type of component of which to return the size.
      * @tparam Component Type of component of which to return the size.
@@ -547,8 +525,8 @@ public:
     version_type destroy(const entity_type entity, const version_type version) {
     version_type destroy(const entity_type entity, const version_type version) {
         ENTT_ASSERT(valid(entity), "Invalid entity");
         ENTT_ASSERT(valid(entity), "Invalid entity");
 
 
-        for(auto &&pdata: pools) {
-            pdata.second.pool->remove(entity);
+        for(auto &&curr: pools) {
+            curr.second.pool->remove(entity);
         }
         }
 
 
         return release_entity(entity, version);
         return release_entity(entity, version);
@@ -570,8 +548,8 @@ public:
                 destroy(*first, entity_traits::to_version(*first) + 1u);
                 destroy(*first, entity_traits::to_version(*first) + 1u);
             }
             }
         } else {
         } else {
-            for(auto &&pdata: pools) {
-                pdata.second.pool->remove(first, last);
+            for(auto &&curr: pools) {
+                curr.second.pool->remove(first, last);
             }
             }
 
 
             release(first, last);
             release(first, last);
@@ -801,8 +779,8 @@ public:
     template<typename... Component>
     template<typename... Component>
     void compact() {
     void compact() {
         if constexpr(sizeof...(Component) == 0) {
         if constexpr(sizeof...(Component) == 0) {
-            for(auto &&pdata: pools) {
-                pdata.second.pool->compact();
+            for(auto &&curr: pools) {
+                curr.second.pool->compact();
             }
             }
         } else {
         } else {
             (assure<Component>()->compact(), ...);
             (assure<Component>()->compact(), ...);
@@ -944,8 +922,8 @@ public:
     template<typename... Component>
     template<typename... Component>
     void clear() {
     void clear() {
         if constexpr(sizeof...(Component) == 0) {
         if constexpr(sizeof...(Component) == 0) {
-            for(auto &&pdata: pools) {
-                pdata.second.pool->clear();
+            for(auto &&curr: pools) {
+                curr.second.pool->clear();
             }
             }
 
 
             each([this](const auto entity) { release_entity(entity, entity_traits::to_version(entity) + 1u); });
             each([this](const auto entity) { release_entity(entity, entity_traits::to_version(entity) + 1u); });
@@ -993,7 +971,7 @@ public:
      */
      */
     [[nodiscard]] bool orphan(const entity_type entity) const {
     [[nodiscard]] bool orphan(const entity_type entity) const {
         ENTT_ASSERT(valid(entity), "Invalid entity");
         ENTT_ASSERT(valid(entity), "Invalid entity");
-        return std::none_of(pools.cbegin(), pools.cend(), [entity](auto &&pdata) { return pdata.second.pool->contains(entity); });
+        return std::none_of(pools.cbegin(), pools.cend(), [entity](auto &&curr) { return curr.second.pool->contains(entity); });
     }
     }
 
 
     /**
     /**
@@ -1173,12 +1151,12 @@ public:
         std::vector<const basic_common_type *> filter(std::distance(from, to));
         std::vector<const basic_common_type *> filter(std::distance(from, to));
 
 
         std::transform(first, last, component.begin(), [this](const auto ctype) {
         std::transform(first, last, component.begin(), [this](const auto ctype) {
-            const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.second.poly->value_type().hash() == ctype; });
+            const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&curr) { return curr.second.info->hash() == ctype; });
             return it == pools.cend() ? nullptr : it->second.pool.get();
             return it == pools.cend() ? nullptr : it->second.pool.get();
         });
         });
 
 
         std::transform(from, to, filter.begin(), [this](const auto ctype) {
         std::transform(from, to, filter.begin(), [this](const auto ctype) {
-            const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&pdata) { return pdata.second.poly->value_type().hash() == ctype; });
+            const auto it = std::find_if(pools.cbegin(), pools.cend(), [ctype](auto &&curr) { return curr.second.info->hash() == ctype; });
             return it == pools.cend() ? nullptr : it->second.pool.get();
             return it == pools.cend() ? nullptr : it->second.pool.get();
         });
         });
 
 
@@ -1448,9 +1426,9 @@ public:
      */
      */
     template<typename Func>
     template<typename Func>
     void visit(entity_type entity, Func func) const {
     void visit(entity_type entity, Func func) const {
-        for(auto &&pdata: pools) {
-            if(pdata.second.pool->contains(entity)) {
-                func(pdata.second.poly->value_type());
+        for(auto &&curr: pools) {
+            if(curr.second.pool->contains(entity)) {
+                func(*curr.second.info);
             }
             }
         }
         }
     }
     }
@@ -1473,8 +1451,8 @@ public:
      */
      */
     template<typename Func>
     template<typename Func>
     void visit(Func func) const {
     void visit(Func func) const {
-        for(auto &&pdata: pools) {
-            func(pdata.second.poly->value_type());
+        for(auto &&curr: pools) {
+            func(*curr.second.info);
         }
         }
     }
     }
 
 

+ 0 - 1
src/entt/entt.hpp

@@ -23,7 +23,6 @@
 #include "entity/helper.hpp"
 #include "entity/helper.hpp"
 #include "entity/observer.hpp"
 #include "entity/observer.hpp"
 #include "entity/organizer.hpp"
 #include "entity/organizer.hpp"
-#include "entity/poly_storage.hpp"
 #include "entity/registry.hpp"
 #include "entity/registry.hpp"
 #include "entity/runtime_view.hpp"
 #include "entity/runtime_view.hpp"
 #include "entity/snapshot.hpp"
 #include "entity/snapshot.hpp"

+ 0 - 1
test/CMakeLists.txt

@@ -188,7 +188,6 @@ SETUP_BASIC_TEST(group entt/entity/group.cpp)
 SETUP_BASIC_TEST(handle entt/entity/handle.cpp)
 SETUP_BASIC_TEST(handle entt/entity/handle.cpp)
 SETUP_BASIC_TEST(helper entt/entity/helper.cpp)
 SETUP_BASIC_TEST(helper entt/entity/helper.cpp)
 SETUP_BASIC_TEST(observer entt/entity/observer.cpp)
 SETUP_BASIC_TEST(observer entt/entity/observer.cpp)
-SETUP_BASIC_TEST(poly_storage entt/entity/poly_storage.cpp)
 SETUP_BASIC_TEST(organizer entt/entity/organizer.cpp)
 SETUP_BASIC_TEST(organizer entt/entity/organizer.cpp)
 SETUP_BASIC_TEST(registry entt/entity/registry.cpp)
 SETUP_BASIC_TEST(registry entt/entity/registry.cpp)
 SETUP_BASIC_TEST(registry_no_eto entt/entity/registry_no_eto.cpp ENTT_NO_ETO)
 SETUP_BASIC_TEST(registry_no_eto entt/entity/registry_no_eto.cpp ENTT_NO_ETO)