Browse Source

sparse_set:
* opaque emplace returns bool
* opaque insert returnes the number of entities actually emplaced

Michele Caini 4 years ago
parent
commit
be87191d0a

+ 14 - 8
src/entt/entity/sparse_set.hpp

@@ -661,10 +661,11 @@ public:
      *
      *
      * @param entt A valid identifier.
      * @param entt A valid identifier.
      * @param value Optional opaque value to forward to mixins, if any.
      * @param value Optional opaque value to forward to mixins, if any.
+     * @return True in case of success, false otherwise.
      */
      */
-    void emplace(const entity_type entt, const void *value = nullptr) {
+    bool emplace(const entity_type entt, const void *value = nullptr) {
         try_emplace(entt, value);
         try_emplace(entt, value);
-        ENTT_ASSERT(contains(entt), "Emplace did not take place");
+        return contains(entt);
     }
     }
 
 
     /**
     /**
@@ -677,18 +678,23 @@ public:
      * @tparam It Type of input iterator.
      * @tparam It Type of input iterator.
      * @param first An iterator to the first element of the range of 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 last An iterator past the last element of the range of entities.
+     * @return Number of entities actually assigned to the sparse set.
      */
      */
     template<typename It>
     template<typename It>
-    void insert(It first, It last) {
+    size_type insert(It first, It last) {
+        size_type count{};
+
         for(; first != last && free_list != null; ++first) {
         for(; first != last && free_list != null; ++first) {
-            emplace(*first);
+            count += emplace(*first);
         }
         }
 
 
         reserve(packed.size() + std::distance(first, last));
         reserve(packed.size() + std::distance(first, last));
 
 
         for(; first != last; ++first) {
         for(; first != last; ++first) {
-            emplace(*first);
+            count += emplace(*first);
         }
         }
+
+        return count;
     }
     }
 
 
     /**
     /**
@@ -740,13 +746,13 @@ public:
      */
      */
     template<typename It>
     template<typename It>
     size_type remove(It first, It last) {
     size_type remove(It first, It last) {
-        size_type found{};
+        size_type count{};
 
 
         for(; first != last; ++first) {
         for(; first != last; ++first) {
-            found += remove(*first);
+            count += remove(*first);
         }
         }
 
 
-        return found;
+        return count;
     }
     }
 
 
     /*! @brief Removes all tombstones from the packed array of a sparse set. */
     /*! @brief Removes all tombstones from the packed array of a sparse set. */

+ 4 - 1
src/entt/entity/storage.hpp

@@ -950,7 +950,10 @@ class sigh_storage_mixin final: public Type {
     void try_emplace(const typename Type::entity_type entt, const void *value) final {
     void try_emplace(const typename Type::entity_type entt, const void *value) final {
         ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
         ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry");
         Type::try_emplace(entt, value);
         Type::try_emplace(entt, value);
-        construction.publish(*owner, entt);
+
+        if(Type::contains(entt)) {
+            construction.publish(*owner, entt);
+        }
     }
     }
 
 
 public:
 public:

+ 8 - 6
test/entt/entity/sigh_storage_mixin.cpp

@@ -47,7 +47,8 @@ TEST(SighStorageMixin, GenericType) {
     pool.on_construct().connect<&listener>(on_construct);
     pool.on_construct().connect<&listener>(on_construct);
     pool.on_destroy().connect<&listener>(on_destroy);
     pool.on_destroy().connect<&listener>(on_destroy);
 
 
-    base.emplace(entities[0u]);
+    ASSERT_TRUE(base.emplace(entities[0u]));
+
     pool.emplace(entities[1u]);
     pool.emplace(entities[1u]);
 
 
     ASSERT_EQ(on_construct.value, 2);
     ASSERT_EQ(on_construct.value, 2);
@@ -64,7 +65,7 @@ TEST(SighStorageMixin, GenericType) {
     ASSERT_EQ(on_destroy.value, 2);
     ASSERT_EQ(on_destroy.value, 2);
     ASSERT_TRUE(pool.empty());
     ASSERT_TRUE(pool.empty());
 
 
-    base.insert(std::begin(entities), std::end(entities));
+    ASSERT_EQ(base.insert(std::begin(entities), std::end(entities)), 2u);
 
 
     ASSERT_EQ(pool.get(entities[0u]), 0);
     ASSERT_EQ(pool.get(entities[0u]), 0);
     ASSERT_EQ(pool.get(entities[1u]), 0);
     ASSERT_EQ(pool.get(entities[1u]), 0);
@@ -112,7 +113,8 @@ TEST(SighStorageMixin, EmptyType) {
     pool.on_construct().connect<&listener>(on_construct);
     pool.on_construct().connect<&listener>(on_construct);
     pool.on_destroy().connect<&listener>(on_destroy);
     pool.on_destroy().connect<&listener>(on_destroy);
 
 
-    base.emplace(entities[0u]);
+    ASSERT_TRUE(base.emplace(entities[0u]));
+
     pool.emplace(entities[1u]);
     pool.emplace(entities[1u]);
 
 
     ASSERT_EQ(on_construct.value, 2);
     ASSERT_EQ(on_construct.value, 2);
@@ -129,7 +131,7 @@ TEST(SighStorageMixin, EmptyType) {
     ASSERT_EQ(on_destroy.value, 2);
     ASSERT_EQ(on_destroy.value, 2);
     ASSERT_TRUE(pool.empty());
     ASSERT_TRUE(pool.empty());
 
 
-    base.insert(std::begin(entities), std::end(entities));
+    ASSERT_EQ(base.insert(std::begin(entities), std::end(entities)), 2u);
 
 
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_TRUE(pool.contains(entities[1u]));
     ASSERT_TRUE(pool.contains(entities[1u]));
@@ -177,7 +179,7 @@ TEST(SighStorageMixin, NonDefaultConstructibleType) {
     pool.on_construct().connect<&listener>(on_construct);
     pool.on_construct().connect<&listener>(on_construct);
     pool.on_destroy().connect<&listener>(on_destroy);
     pool.on_destroy().connect<&listener>(on_destroy);
 
 
-    ASSERT_DEATH(base.emplace(entities[0u]), "");
+    ASSERT_FALSE(base.emplace(entities[0u]));
 
 
     pool.emplace(entities[1u], 3);
     pool.emplace(entities[1u], 3);
 
 
@@ -194,7 +196,7 @@ TEST(SighStorageMixin, NonDefaultConstructibleType) {
     ASSERT_EQ(on_destroy.value, 1);
     ASSERT_EQ(on_destroy.value, 1);
     ASSERT_TRUE(pool.empty());
     ASSERT_TRUE(pool.empty());
 
 
-    ASSERT_DEATH(base.insert(std::begin(entities), std::end(entities)), "");
+    ASSERT_EQ(base.insert(std::begin(entities), std::end(entities)), 0u);
 
 
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
     ASSERT_FALSE(pool.contains(entities[1u]));

+ 14 - 11
test/entt/entity/sparse_set.cpp

@@ -263,12 +263,12 @@ TEST(SparseSet, Emplace) {
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
 
 
     ASSERT_TRUE(set.empty());
     ASSERT_TRUE(set.empty());
+    ASSERT_TRUE(set.emplace(entities[0u]));
 
 
-    set.emplace(entities[0u]);
     set.erase(entities[0u]);
     set.erase(entities[0u]);
 
 
-    set.emplace(entities[1u]);
-    set.emplace(entities[0u]);
+    ASSERT_TRUE(set.emplace(entities[1u]));
+    ASSERT_TRUE(set.emplace(entities[0u]));
 
 
     ASSERT_DEATH(set.emplace(traits_type::combine(3, 1)), "");
     ASSERT_DEATH(set.emplace(traits_type::combine(3, 1)), "");
     ASSERT_DEATH(set.emplace(entities[1u]), "");
     ASSERT_DEATH(set.emplace(entities[1u]), "");
@@ -279,8 +279,9 @@ TEST(SparseSet, Emplace) {
     ASSERT_EQ(set.index(entities[1u]), 0u);
     ASSERT_EQ(set.index(entities[1u]), 0u);
 
 
     set.erase(std::begin(entities), std::end(entities));
     set.erase(std::begin(entities), std::end(entities));
-    set.emplace(entities[1u]);
-    set.emplace(entities[0u]);
+
+    ASSERT_TRUE(set.emplace(entities[1u]));
+    ASSERT_TRUE(set.emplace(entities[0u]));
 
 
     ASSERT_EQ(set.at(0u), entities[1u]);
     ASSERT_EQ(set.at(0u), entities[1u]);
     ASSERT_EQ(set.at(1u), entities[0u]);
     ASSERT_EQ(set.at(1u), entities[0u]);
@@ -292,14 +293,13 @@ TEST(SparseSet, EmplaceOutOfBounds) {
     entt::sparse_set set{entt::deletion_policy::in_place};
     entt::sparse_set set{entt::deletion_policy::in_place};
     entt::entity entities[2u]{entt::entity{0}, entt::entity{ENTT_SPARSE_PAGE}};
     entt::entity entities[2u]{entt::entity{0}, entt::entity{ENTT_SPARSE_PAGE}};
 
 
-    set.emplace(entities[0u]);
-
+    ASSERT_TRUE(set.emplace(entities[0u]));
     ASSERT_EQ(set.extent(), ENTT_SPARSE_PAGE);
     ASSERT_EQ(set.extent(), ENTT_SPARSE_PAGE);
     ASSERT_EQ(set.index(entities[0u]), 0u);
     ASSERT_EQ(set.index(entities[0u]), 0u);
 
 
     set.erase(entities[0u]);
     set.erase(entities[0u]);
-    set.emplace(entities[1u]);
 
 
+    ASSERT_TRUE(set.emplace(entities[1u]));
     ASSERT_EQ(set.extent(), 2u * ENTT_SPARSE_PAGE);
     ASSERT_EQ(set.extent(), 2u * ENTT_SPARSE_PAGE);
     ASSERT_EQ(set.index(entities[1u]), 0u);
     ASSERT_EQ(set.index(entities[1u]), 0u);
 }
 }
@@ -309,8 +309,10 @@ TEST(SparseSet, Insert) {
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
     entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
 
 
     set.emplace(entt::entity{12});
     set.emplace(entt::entity{12});
-    set.insert(std::end(entities), std::end(entities));
-    set.insert(std::begin(entities), std::end(entities));
+
+    ASSERT_EQ(set.insert(std::end(entities), std::end(entities)), 0u);
+    ASSERT_EQ(set.insert(std::begin(entities), std::end(entities)), 2u);
+
     set.emplace(entt::entity{24});
     set.emplace(entt::entity{24});
 
 
     ASSERT_TRUE(set.contains(entities[0u]));
     ASSERT_TRUE(set.contains(entities[0u]));
@@ -332,7 +334,8 @@ TEST(SparseSet, Insert) {
     ASSERT_EQ(set.data()[set.index(entt::entity{24})], entt::entity{24});
     ASSERT_EQ(set.data()[set.index(entt::entity{24})], entt::entity{24});
 
 
     set.erase(std::begin(entities), std::end(entities));
     set.erase(std::begin(entities), std::end(entities));
-    set.insert(std::rbegin(entities), std::rend(entities));
+
+    ASSERT_EQ(set.insert(std::rbegin(entities), std::rend(entities)), 2u);
 
 
     ASSERT_EQ(set.size(), 4u);
     ASSERT_EQ(set.size(), 4u);
     ASSERT_EQ(set.at(1u), entities[0u]);
     ASSERT_EQ(set.at(1u), entities[0u]);

+ 16 - 11
test/entt/entity/storage.cpp

@@ -592,7 +592,8 @@ TEST(Storage, TypeFromBase) {
     ASSERT_FALSE(pool.contains(entities[1u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
 
 
     int instance = 42;
     int instance = 42;
-    base.emplace(entities[0u], &instance);
+
+    ASSERT_TRUE(base.emplace(entities[0u], &instance));
 
 
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
@@ -600,7 +601,8 @@ TEST(Storage, TypeFromBase) {
     ASSERT_EQ(pool.get(entities[0u]), 42);
     ASSERT_EQ(pool.get(entities[0u]), 42);
 
 
     base.erase(entities[0u]);
     base.erase(entities[0u]);
-    base.insert(std::begin(entities), std::end(entities));
+
+    ASSERT_EQ(base.insert(std::begin(entities), std::end(entities)), 2u);
 
 
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_TRUE(pool.contains(entities[1u]));
     ASSERT_TRUE(pool.contains(entities[1u]));
@@ -624,14 +626,16 @@ TEST(Storage, EmptyTypeFromBase) {
     ASSERT_FALSE(pool.contains(entities[1u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
 
 
     empty_stable_type instance{};
     empty_stable_type instance{};
-    base.emplace(entities[0u], &instance);
+
+    ASSERT_TRUE(base.emplace(entities[0u], &instance));
 
 
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
     ASSERT_EQ(base.get(entities[0u]), nullptr);
     ASSERT_EQ(base.get(entities[0u]), nullptr);
 
 
     base.erase(entities[0u]);
     base.erase(entities[0u]);
-    base.insert(std::begin(entities), std::end(entities));
+
+    ASSERT_EQ(base.insert(std::begin(entities), std::end(entities)), 2u);
 
 
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_TRUE(pool.contains(entities[1u]));
     ASSERT_TRUE(pool.contains(entities[1u]));
@@ -655,7 +659,7 @@ TEST(Storage, NonDefaultConstructibleTypeFromBase) {
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
 
 
-    ASSERT_DEATH(base.emplace(entities[0u]), "");
+    ASSERT_FALSE(base.emplace(entities[0u]));
 
 
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
@@ -663,7 +667,8 @@ TEST(Storage, NonDefaultConstructibleTypeFromBase) {
     ASSERT_TRUE(pool.empty());
     ASSERT_TRUE(pool.empty());
 
 
     non_default_constructible instance{3};
     non_default_constructible instance{3};
-    base.emplace(entities[0u], &instance);
+
+    ASSERT_TRUE(base.emplace(entities[0u], &instance));
 
 
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
@@ -673,7 +678,7 @@ TEST(Storage, NonDefaultConstructibleTypeFromBase) {
     ASSERT_TRUE(pool.empty());
     ASSERT_TRUE(pool.empty());
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[0u]));
 
 
-    ASSERT_DEATH(base.insert(std::begin(entities), std::end(entities)), "");
+    ASSERT_EQ(base.insert(std::begin(entities), std::end(entities)), 0u);
 
 
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
@@ -693,7 +698,7 @@ TEST(Storage, NonCopyConstructibleTypeFromBase) {
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
 
 
-    base.emplace(entities[0u]);
+    ASSERT_TRUE(base.emplace(entities[0u]));
 
 
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
@@ -702,7 +707,7 @@ TEST(Storage, NonCopyConstructibleTypeFromBase) {
 
 
     std::unique_ptr<int> instance = std::make_unique<int>(3);
     std::unique_ptr<int> instance = std::make_unique<int>(3);
 
 
-    ASSERT_DEATH(base.emplace(entities[1u], &instance), "");
+    ASSERT_FALSE(base.emplace(entities[1u], &instance));
 
 
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
     ASSERT_FALSE(pool.contains(entities[1u]));
@@ -712,7 +717,7 @@ TEST(Storage, NonCopyConstructibleTypeFromBase) {
     ASSERT_TRUE(pool.empty());
     ASSERT_TRUE(pool.empty());
     ASSERT_FALSE(pool.contains(entities[0u]));
     ASSERT_FALSE(pool.contains(entities[0u]));
 
 
-    base.insert(std::begin(entities), std::end(entities));
+    ASSERT_EQ(base.insert(std::begin(entities), std::end(entities)), 2u);
 
 
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_TRUE(pool.contains(entities[0u]));
     ASSERT_TRUE(pool.contains(entities[1u]));
     ASSERT_TRUE(pool.contains(entities[1u]));
@@ -1119,7 +1124,7 @@ TEST(Storage, IterableIteratorConversion) {
 
 
     typename entt::storage<boxed_int>::iterable::iterator it = pool.each().begin();
     typename entt::storage<boxed_int>::iterable::iterator it = pool.each().begin();
     typename entt::storage<boxed_int>::const_iterable::const_iterator cit = it;
     typename entt::storage<boxed_int>::const_iterable::const_iterator cit = it;
-    
+
     static_assert(std::is_same_v<decltype(*it), std::tuple<entt::entity, boxed_int &>>);
     static_assert(std::is_same_v<decltype(*it), std::tuple<entt::entity, boxed_int &>>);
     static_assert(std::is_same_v<decltype(*cit), std::tuple<entt::entity, const boxed_int &>>);
     static_assert(std::is_same_v<decltype(*cit), std::tuple<entt::entity, const boxed_int &>>);