Browse Source

sparse_set: ::contains uses the right version mask

Michele Caini 2 năm trước cách đây
mục cha
commit
9e62e1dab6

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

@@ -724,8 +724,9 @@ public:
     [[nodiscard]] bool contains(const entity_type entt) const noexcept {
     [[nodiscard]] bool contains(const entity_type entt) const noexcept {
         const auto elem = sparse_ptr(entt);
         const auto elem = sparse_ptr(entt);
         constexpr auto cap = traits_type::entity_mask;
         constexpr auto cap = traits_type::entity_mask;
+        constexpr auto mask = traits_type::to_integral(null) & ~cap;
         // testing versions permits to avoid accessing the packed array
         // testing versions permits to avoid accessing the packed array
-        return elem && (((~cap & traits_type::to_integral(entt)) ^ traits_type::to_integral(*elem)) < cap);
+        return elem && (((mask & traits_type::to_integral(entt)) ^ traits_type::to_integral(*elem)) < cap);
     }
     }
 
 
     /**
     /**

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

@@ -21,7 +21,7 @@ struct custom_entity_traits {
     using entity_type = std::uint32_t;
     using entity_type = std::uint32_t;
     using version_type = std::uint16_t;
     using version_type = std::uint16_t;
     static constexpr entity_type entity_mask = 0x3FFFF; // 18b
     static constexpr entity_type entity_mask = 0x3FFFF; // 18b
-    static constexpr entity_type version_mask = 0x3FFF; // 14b
+    static constexpr entity_type version_mask = 0x0FFF; // 12b
 };
 };
 
 
 template<>
 template<>
@@ -765,6 +765,36 @@ TYPED_TEST(SparseSet, Contains) {
 
 
         ASSERT_FALSE(set.contains(entity));
         ASSERT_FALSE(set.contains(entity));
         ASSERT_FALSE(set.contains(other));
         ASSERT_FALSE(set.contains(other));
+
+        if constexpr(traits_type::to_integral(entt::tombstone) != ~traits_type::entity_type{}) {
+            // test reserved bits, if any
+            constexpr entity_type reserved{traits_type::to_integral(entity) | (traits_type::to_integral(entt::tombstone) + 1u)};
+
+            ASSERT_NE(entity, reserved);
+
+            set.push(reserved);
+
+            ASSERT_TRUE(set.contains(entity));
+            ASSERT_TRUE(set.contains(reserved));
+
+            ASSERT_NE(*set.find(entity), entity);
+            ASSERT_EQ(*set.find(entity), reserved);
+
+            set.bump(entity);
+
+            ASSERT_TRUE(set.contains(entity));
+            ASSERT_TRUE(set.contains(reserved));
+
+            ASSERT_NE(*set.find(reserved), reserved);
+            ASSERT_EQ(*set.find(reserved), entity);
+
+            set.erase(reserved);
+
+            ASSERT_FALSE(set.contains(entity));
+            ASSERT_FALSE(set.contains(reserved));
+
+            ASSERT_EQ(set.find(reserved), set.end());
+        }
     }
     }
 }
 }