Browse Source

sparse_set/storage: value type from base, if any

Michele Caini 4 years ago
parent
commit
46e5d96ced

+ 26 - 2
src/entt/entity/sparse_set.hpp

@@ -11,6 +11,7 @@
 #include "../core/algorithm.hpp"
 #include "../core/any.hpp"
 #include "../core/memory.hpp"
+#include "../core/type_info.hpp"
 #include "entity.hpp"
 #include "fwd.hpp"
 
@@ -282,14 +283,14 @@ public:
 
     /*! @brief Default constructor. */
     basic_sparse_set()
-        : basic_sparse_set{allocator_type{}} {}
+        : basic_sparse_set{type_id<void>()} {}
 
     /**
      * @brief Constructs an empty container with a given allocator.
      * @param allocator The allocator to use.
      */
     explicit basic_sparse_set(const allocator_type &allocator)
-        : basic_sparse_set{deletion_policy::swap_and_pop, allocator} {}
+        : basic_sparse_set{type_id<void>(), deletion_policy::swap_and_pop, allocator} {}
 
     /**
      * @brief Constructs an empty container with the given policy and allocator.
@@ -297,8 +298,18 @@ public:
      * @param allocator The allocator to use (possibly default-constructed).
      */
     explicit basic_sparse_set(deletion_policy pol, const allocator_type &allocator = {})
+        : basic_sparse_set{type_id<void>(), pol, allocator} {}
+
+    /**
+     * @brief Constructs an empty container with the given policy and allocator.
+     * @param value Returned value type, if any.
+     * @param pol Type of deletion policy.
+     * @param allocator The allocator to use (possibly default-constructed).
+     */
+    explicit basic_sparse_set(const type_info &value, deletion_policy pol = deletion_policy::swap_and_pop, const allocator_type &allocator = {})
         : sparse{allocator},
           packed{allocator},
+          info{&value},
           free_list{tombstone},
           mode{pol} {}
 
@@ -309,6 +320,7 @@ public:
     basic_sparse_set(basic_sparse_set &&other) ENTT_NOEXCEPT
         : sparse{std::move(other.sparse)},
           packed{std::move(other.packed)},
+          info{other.info},
           free_list{std::exchange(other.free_list, tombstone)},
           mode{other.mode} {}
 
@@ -320,6 +332,7 @@ public:
     basic_sparse_set(basic_sparse_set &&other, const allocator_type &allocator) ENTT_NOEXCEPT
         : sparse{std::move(other.sparse), allocator},
           packed{std::move(other.packed), allocator},
+          info{other.info},
           free_list{std::exchange(other.free_list, tombstone)},
           mode{other.mode} {
         ENTT_ASSERT(alloc_traits::is_always_equal::value || packed.get_allocator() == other.packed.get_allocator(), "Copying a sparse set is not allowed");
@@ -341,6 +354,7 @@ public:
         release_sparse_pages();
         sparse = std::move(other.sparse);
         packed = std::move(other.packed);
+        info = other.info;
         free_list = std::exchange(other.free_list, tombstone);
         mode = other.mode;
         return *this;
@@ -354,6 +368,7 @@ public:
         using std::swap;
         swap(sparse, other.sparse);
         swap(packed, other.packed);
+        swap(info, other.info);
         swap(free_list, other.free_list);
         swap(mode, other.mode);
     }
@@ -835,12 +850,21 @@ public:
         }
     }
 
+    /**
+     * @brief Returned value type, if any.
+     * @return Returned value type, if any.
+     */
+    const type_info &type() const ENTT_NOEXCEPT {
+        return *info;
+    }
+
     /*! @brief Forwards variables to mixins, if any. */
     virtual void bind(any) ENTT_NOEXCEPT {}
 
 private:
     sparse_container_type sparse;
     packed_container_type packed;
+    const type_info *info;
     entity_type free_list;
     deletion_policy mode;
 };

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

@@ -13,6 +13,7 @@
 #include "../core/any.hpp"
 #include "../core/compressed_pair.hpp"
 #include "../core/memory.hpp"
+#include "../core/type_info.hpp"
 #include "../core/type_traits.hpp"
 #include "../signal/sigh.hpp"
 #include "component.hpp"
@@ -390,15 +391,14 @@ public:
 
     /*! @brief Default constructor. */
     basic_storage()
-        : base_type{deletion_policy{comp_traits::in_place_delete::value}},
-          packed{} {}
+        : basic_storage{allocator_type{}} {}
 
     /**
      * @brief Constructs an empty storage with a given allocator.
      * @param allocator The allocator to use.
      */
     explicit basic_storage(const allocator_type &allocator)
-        : base_type{deletion_policy{comp_traits::in_place_delete::value}, allocator},
+        : base_type{type_id<value_type>(), deletion_policy{comp_traits::in_place_delete::value}, allocator},
           packed{container_type{allocator}, allocator} {}
 
     /**
@@ -743,14 +743,14 @@ public:
 
     /*! @brief Default constructor. */
     basic_storage()
-        : base_type{deletion_policy{comp_traits::in_place_delete::value}} {}
+        : basic_storage{allocator_type{}} {}
 
     /**
      * @brief Constructs an empty container with a given allocator.
      * @param allocator The allocator to use.
      */
     explicit basic_storage(const allocator_type &allocator)
-        : base_type{deletion_policy{comp_traits::in_place_delete::value}, allocator} {}
+        : base_type{type_id<value_type>(), deletion_policy{comp_traits::in_place_delete::value}, allocator} {}
 
     /**
      * @brief Move constructor.

+ 1 - 0
test/entt/entity/sparse_set.cpp

@@ -19,6 +19,7 @@ TEST(SparseSet, Functionalities) {
     entt::sparse_set set;
 
     ASSERT_NO_THROW([[maybe_unused]] auto alloc = set.get_allocator());
+    ASSERT_EQ(set.type(), entt::type_id<void>());
 
     set.reserve(42);
 

+ 23 - 0
test/entt/entity/storage.cpp

@@ -73,6 +73,7 @@ TEST(Storage, Functionalities) {
     entt::storage<int> pool;
 
     ASSERT_NO_THROW([[maybe_unused]] auto alloc = pool.get_allocator());
+    ASSERT_EQ(pool.type(), entt::type_id<int>());
 
     pool.reserve(42);
 
@@ -141,11 +142,13 @@ TEST(Storage, Move) {
 
     ASSERT_TRUE(std::is_move_constructible_v<decltype(pool)>);
     ASSERT_TRUE(std::is_move_assignable_v<decltype(pool)>);
+    ASSERT_EQ(pool.type(), entt::type_id<int>());
 
     entt::storage<int> other{std::move(pool)};
 
     ASSERT_TRUE(pool.empty());
     ASSERT_FALSE(other.empty());
+    ASSERT_EQ(other.type(), entt::type_id<int>());
     ASSERT_EQ(pool.at(0u), static_cast<entt::entity>(entt::null));
     ASSERT_EQ(other.at(0u), entt::entity{3});
     ASSERT_EQ(other.get(entt::entity{3}), 3);
@@ -184,6 +187,9 @@ TEST(Storage, Swap) {
 
     pool.swap(other);
 
+    ASSERT_EQ(pool.type(), entt::type_id<int>());
+    ASSERT_EQ(other.type(), entt::type_id<int>());
+
     ASSERT_EQ(pool.size(), 1u);
     ASSERT_EQ(other.size(), 1u);
 
@@ -209,6 +215,9 @@ TEST(Storage, StableSwap) {
 
     pool.swap(other);
 
+    ASSERT_EQ(pool.type(), entt::type_id<stable_type>());
+    ASSERT_EQ(other.type(), entt::type_id<stable_type>());
+
     ASSERT_EQ(pool.size(), 2u);
     ASSERT_EQ(other.size(), 1u);
 
@@ -224,6 +233,8 @@ TEST(Storage, EmptyType) {
     pool.emplace(entt::entity{99});
 
     ASSERT_NO_THROW([[maybe_unused]] auto alloc = pool.get_allocator());
+    ASSERT_EQ(pool.type(), entt::type_id<empty_stable_type>());
+
     ASSERT_TRUE(pool.contains(entt::entity{99}));
     ASSERT_DEATH(pool.get(entt::entity{}), "");
 
@@ -574,6 +585,9 @@ TEST(Storage, TypeFromBase) {
     entt::sparse_set &base = pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
 
+    ASSERT_EQ(pool.type(), entt::type_id<int>());
+    ASSERT_EQ(pool.type(), base.type());
+
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
 
@@ -602,6 +616,9 @@ TEST(Storage, EmptyTypeFromBase) {
     entt::sparse_set &base = pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
 
+    ASSERT_EQ(pool.type(), entt::type_id<empty_stable_type>());
+    ASSERT_EQ(pool.type(), base.type());
+
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
 
@@ -630,6 +647,9 @@ TEST(Storage, NonDefaultConstructibleTypeFromBase) {
     entt::sparse_set &base = pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
 
+    ASSERT_EQ(pool.type(), entt::type_id<non_default_constructible>());
+    ASSERT_EQ(pool.type(), base.type());
+
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
 
@@ -665,6 +685,9 @@ TEST(Storage, NonCopyConstructibleTypeFromBase) {
     entt::sparse_set &base = pool;
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
 
+    ASSERT_EQ(pool.type(), entt::type_id<std::unique_ptr<int>>());
+    ASSERT_EQ(pool.type(), base.type());
+
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));