storage: fix cross range-erase can break when using built-in iterators (close #914)
This commit is contained in:
@@ -331,14 +331,17 @@ protected:
|
||||
*/
|
||||
void pop(basic_iterator first, basic_iterator last) override {
|
||||
for(; first != last; ++first) {
|
||||
// cannot use first.index() because it would break with cross iterators
|
||||
auto &elem = element_at(base_type::index(*first));
|
||||
|
||||
if constexpr(comp_traits::in_place_delete) {
|
||||
base_type::in_place_pop(first);
|
||||
std::destroy_at(std::addressof(element_at(static_cast<size_type>(first.index()))));
|
||||
} else {
|
||||
auto &elem = element_at(base_type::size() - 1u);
|
||||
// destroying on exit allows reentrant destructors
|
||||
[[maybe_unused]] auto unused = std::exchange(element_at(static_cast<size_type>(first.index())), std::move(elem));
|
||||
std::destroy_at(std::addressof(elem));
|
||||
} else {
|
||||
auto &other = element_at(base_type::size() - 1u);
|
||||
// destroying on exit allows reentrant destructors
|
||||
[[maybe_unused]] auto unused = std::exchange(elem, std::move(other));
|
||||
std::destroy_at(std::addressof(other));
|
||||
base_type::swap_and_pop(first);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,6 +364,21 @@ TEST(Storage, Erase) {
|
||||
ASSERT_EQ(*pool.begin(), 1);
|
||||
}
|
||||
|
||||
TEST(Storage, CrossErase) {
|
||||
entt::sparse_set set;
|
||||
entt::storage<int> pool;
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
|
||||
pool.emplace(entities[0u], 3);
|
||||
pool.emplace(entities[1u], 42);
|
||||
set.emplace(entities[1u]);
|
||||
pool.erase(set.begin(), set.end());
|
||||
|
||||
ASSERT_TRUE(pool.contains(entities[0u]));
|
||||
ASSERT_FALSE(pool.contains(entities[1u]));
|
||||
ASSERT_EQ(pool.raw()[0u][0u], 3);
|
||||
}
|
||||
|
||||
TEST(Storage, StableErase) {
|
||||
entt::storage<stable_type> pool;
|
||||
entt::entity entities[3u]{entt::entity{3}, entt::entity{42}, entt::entity{9}};
|
||||
@@ -458,6 +473,21 @@ TEST(Storage, StableErase) {
|
||||
ASSERT_EQ(pool.get(entities[2u]).value, 1);
|
||||
}
|
||||
|
||||
TEST(Storage, CrossStableErase) {
|
||||
entt::sparse_set set;
|
||||
entt::storage<stable_type> pool;
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
|
||||
pool.emplace(entities[0u], 3);
|
||||
pool.emplace(entities[1u], 42);
|
||||
set.emplace(entities[1u]);
|
||||
pool.erase(set.begin(), set.end());
|
||||
|
||||
ASSERT_TRUE(pool.contains(entities[0u]));
|
||||
ASSERT_FALSE(pool.contains(entities[1u]));
|
||||
ASSERT_EQ(pool.raw()[0u][0u].value, 3);
|
||||
}
|
||||
|
||||
TEST(Storage, Remove) {
|
||||
entt::storage<int> pool;
|
||||
entt::entity entities[3u]{entt::entity{3}, entt::entity{42}, entt::entity{9}};
|
||||
@@ -492,6 +522,21 @@ TEST(Storage, Remove) {
|
||||
ASSERT_EQ(*pool.begin(), 1);
|
||||
}
|
||||
|
||||
TEST(Storage, CrossRemove) {
|
||||
entt::sparse_set set;
|
||||
entt::storage<int> pool;
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
|
||||
pool.emplace(entities[0u], 3);
|
||||
pool.emplace(entities[1u], 42);
|
||||
set.emplace(entities[1u]);
|
||||
pool.remove(set.begin(), set.end());
|
||||
|
||||
ASSERT_TRUE(pool.contains(entities[0u]));
|
||||
ASSERT_FALSE(pool.contains(entities[1u]));
|
||||
ASSERT_EQ(pool.raw()[0u][0u], 3);
|
||||
}
|
||||
|
||||
TEST(Storage, StableRemove) {
|
||||
entt::storage<stable_type> pool;
|
||||
entt::entity entities[3u]{entt::entity{3}, entt::entity{42}, entt::entity{9}};
|
||||
@@ -589,6 +634,21 @@ TEST(Storage, StableRemove) {
|
||||
ASSERT_EQ(pool.get(entities[2u]).value, 1);
|
||||
}
|
||||
|
||||
TEST(Storage, CrossStableRemove) {
|
||||
entt::sparse_set set;
|
||||
entt::storage<stable_type> pool;
|
||||
entt::entity entities[2u]{entt::entity{3}, entt::entity{42}};
|
||||
|
||||
pool.emplace(entities[0u], 3);
|
||||
pool.emplace(entities[1u], 42);
|
||||
set.emplace(entities[1u]);
|
||||
pool.remove(set.begin(), set.end());
|
||||
|
||||
ASSERT_TRUE(pool.contains(entities[0u]));
|
||||
ASSERT_FALSE(pool.contains(entities[1u]));
|
||||
ASSERT_EQ(pool.raw()[0u][0u].value, 3);
|
||||
}
|
||||
|
||||
TEST(Storage, TypeFromBase) {
|
||||
entt::storage<int> pool;
|
||||
entt::sparse_set &base = pool;
|
||||
|
||||
Reference in New Issue
Block a user