Jelajahi Sumber

view: make all unoptimized single type views check for tombstones

Michele Caini 4 tahun lalu
induk
melakukan
0ec7631310
2 mengubah file dengan 43 tambahan dan 5 penghapusan
  1. 2 5
      src/entt/entity/view.hpp
  2. 41 0
      test/entt/entity/view.cpp

+ 2 - 5
src/entt/entity/view.hpp

@@ -106,10 +106,8 @@ private:
 
 template<typename Type, typename It, std::size_t Component, std::size_t Exclude>
 class view_iterator final {
-    static constexpr auto is_multi_type_v = ((Component + Exclude) != 0u);
-
     [[nodiscard]] bool valid() const {
-        return (is_multi_type_v || (*it != tombstone))
+        return ((Component != 0u) || (*it != tombstone))
                && std::apply([entt = *it](const auto *...curr) { return (curr->contains(entt) && ...); }, pools)
                && std::apply([entt = *it](const auto *...curr) { return (!curr->contains(entt) && ...); }, filter);
     }
@@ -232,7 +230,6 @@ class basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>> {
     template<typename Comp>
     using storage_type_t = constness_as_t<typename storage_traits<Entity, std::remove_const_t<Comp>>::storage_type, Comp>;
 
-    static constexpr bool is_multi_type_v = ((sizeof...(Component) + sizeof...(Exclude)) != 1u);
     using basic_common_type = std::common_type_t<typename storage_type_t<Component>::base_type...>;
 
     class iterable final {
@@ -327,7 +324,7 @@ class basic_view<Entity, get_t<Component...>, exclude_t<Exclude...>> {
         for(const auto curr: internal::iterable_storage{*std::get<Comp>(pools)}) {
             const auto entt = std::get<0>(curr);
 
-            if((is_multi_type_v || (entt != tombstone))
+            if(((sizeof...(Component) != 1u) || (entt != tombstone))
                && ((Comp == Index || std::get<Index>(pools)->contains(entt)) && ...)
                && std::apply([entt](const auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) {
                 if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) {

+ 41 - 0
test/entt/entity/view.cpp

@@ -1163,6 +1163,47 @@ TEST(MultiComponentView, StableType) {
     ASSERT_EQ(view.size_hint(), 1u);
 }
 
+TEST(MultiComponentView, StableTypeWithExcludedComponent) {
+    entt::registry registry;
+    auto view = registry.view<stable_type>(entt::exclude<int>).use<stable_type>();
+
+    const auto entity = registry.create();
+    const auto other = registry.create();
+
+    registry.emplace<stable_type>(entity, 0);
+    registry.emplace<stable_type>(other, 42);
+    registry.emplace<int>(entity);
+
+    ASSERT_EQ(view.size_hint(), 2u);
+    ASSERT_FALSE(view.contains(entity));
+    ASSERT_TRUE(view.contains(other));
+
+    registry.destroy(entity);
+
+    ASSERT_EQ(view.size_hint(), 2u);
+    ASSERT_FALSE(view.contains(entity));
+    ASSERT_TRUE(view.contains(other));
+
+    for(auto entt: view) {
+        constexpr entt::entity tombstone = entt::tombstone;
+        ASSERT_NE(entt, tombstone);
+        ASSERT_EQ(entt, other);
+    }
+
+    for(auto [entt, comp]: view.each()) {
+        constexpr entt::entity tombstone = entt::tombstone;
+        ASSERT_NE(entt, tombstone);
+        ASSERT_EQ(entt, other);
+        ASSERT_EQ(comp.value, 42);
+    }
+
+    view.each([other](const auto entt, auto &&...) {
+        constexpr entt::entity tombstone = entt::tombstone;
+        ASSERT_NE(entt, tombstone);
+        ASSERT_EQ(entt, other);
+    });
+}
+
 TEST(MultiComponentView, SameComponentTypes) {
     entt::registry registry;
     typename entt::storage_traits<entt::entity, int>::storage_type storage;