Jelajahi Sumber

registry: support to named context variables (see emplace_hint)

Michele Caini 4 tahun lalu
induk
melakukan
77a399738c
2 mengubah file dengan 60 tambahan dan 18 penghapusan
  1. 22 15
      src/entt/entity/registry.hpp
  2. 38 3
      test/entt/entity/registry.cpp

+ 22 - 15
src/entt/entity/registry.hpp

@@ -159,41 +159,48 @@ template<typename ILhs, typename IRhs>
 }
 
 struct registry_context {
+    template<typename Type, typename... Args>
+    Type &emplace_hint(const id_type id, Args &&...args) {
+        return any_cast<Type &>(data.try_emplace(id, std::in_place_type<Type>, std::forward<Args>(args)...).first->second);
+    }
+
     template<typename Type, typename... Args>
     Type &emplace(Args &&...args) {
-        return any_cast<Type &>(data.try_emplace(type_id<Type>().hash(), std::in_place_type<Type>, std::forward<Args>(args)...).first->second);
+        return emplace_hint<Type>(type_id<Type>().hash(), std::forward<Args>(args)...);
     }
 
     template<typename Type>
-    void erase() {
-        data.erase(type_id<Type>().hash());
+    bool erase(const id_type id = type_id<Type>().hash()) {
+        const auto it = data.find(id);
+        return it != data.end() && it->second.type() == type_id<Type>() ? (data.erase(it), true) : false;
     }
 
     template<typename Type>
-    [[nodiscard]] std::add_const_t<Type> &at() const {
-        return any_cast<std::add_const_t<Type> &>(data.at(type_id<Type>().hash()));
+    [[nodiscard]] std::add_const_t<Type> &at(const id_type id = type_id<Type>().hash()) const {
+        return any_cast<std::add_const_t<Type> &>(data.at(id));
     }
 
     template<typename Type>
-    [[nodiscard]] Type &at() {
-        return any_cast<Type &>(data.at(type_id<Type>().hash()));
+    [[nodiscard]] Type &at(const id_type id = type_id<Type>().hash()) {
+        return any_cast<Type &>(data.at(id));
     }
 
     template<typename Type>
-    [[nodiscard]] std::add_const_t<Type> *find() const {
-        auto it = data.find(type_id<Type>().hash());
-        return it == data.cend() ? nullptr : any_cast<std::add_const_t<Type>>(&it->second);
+    [[nodiscard]] std::add_const_t<Type> *find(const id_type id = type_id<Type>().hash()) const {
+        const auto it = data.find(id);
+        return it != data.cend() ? any_cast<std::add_const_t<Type>>(&it->second) : nullptr;
     }
 
     template<typename Type>
-    [[nodiscard]] Type *find() {
-        auto it = data.find(type_id<Type>().hash());
-        return it == data.end() ? nullptr : any_cast<Type>(&it->second);
+    [[nodiscard]] Type *find(const id_type id = type_id<Type>().hash()) {
+        const auto it = data.find(id);
+        return it != data.end() ? any_cast<Type>(&it->second) : nullptr;
     }
 
     template<typename Type>
-    [[nodiscard]] bool contains() const {
-        return data.contains(type_id<Type>().hash());
+    [[nodiscard]] bool contains(const id_type id = type_id<Type>().hash()) const {
+        const auto it = data.find(id);
+        return it != data.end() && it->second.type() == type_id<Type>();
     }
 
 private:

+ 38 - 3
test/entt/entity/registry.cpp

@@ -83,17 +83,19 @@ TEST(Registry, Context) {
     ASSERT_NE(ctx.find<const char>(), nullptr);
     ASSERT_NE(cctx.find<const int>(), nullptr);
 
-    ctx.erase<int>();
+    ASSERT_FALSE(ctx.erase<double>());
+    ASSERT_TRUE(ctx.erase<int>());
 
     ASSERT_TRUE(ctx.contains<const char>());
     ASSERT_FALSE(cctx.contains<const int>());
     ASSERT_NE(ctx.find<char>(), nullptr);
     ASSERT_EQ(cctx.find<int>(), nullptr);
 
-    ctx.erase<char>();
+    ASSERT_FALSE(ctx.erase<int>());
+    ASSERT_TRUE(ctx.erase<char>());
+
     ctx.emplace<char>('c');
     ctx.emplace<int>(42);
-    ;
 
     ASSERT_EQ(ctx.emplace<char>('a'), 'c');
     ASSERT_EQ(ctx.find<const char>(), cctx.find<char>());
@@ -109,6 +111,39 @@ TEST(Registry, Context) {
     ASSERT_EQ(cctx.find<double>(), nullptr);
 }
 
+TEST(Registry, ContextHint) {
+    using namespace entt::literals;
+
+    entt::registry registry;
+    auto &ctx = registry.ctx();
+    const auto &cctx = std::as_const(registry).ctx();
+
+    ctx.emplace<int>(42);
+    ctx.emplace_hint<int>("other"_hs, 3);
+
+    ASSERT_TRUE(ctx.contains<int>());
+    ASSERT_TRUE(cctx.contains<const int>("other"_hs));
+    ASSERT_FALSE(ctx.contains<char>("other"_hs));
+
+    ASSERT_NE(cctx.find<const int>(), nullptr);
+    ASSERT_NE(ctx.find<int>("other"_hs), nullptr);
+    ASSERT_EQ(cctx.find<const char>("other"_hs), nullptr);
+
+    ASSERT_EQ(ctx.at<int>(), 42);
+    ASSERT_EQ(cctx.at<const int>("other"_hs), 3);
+
+    ASSERT_FALSE(ctx.erase<char>("other"_hs));
+    ASSERT_TRUE(ctx.erase<int>());
+
+    ASSERT_TRUE(cctx.contains<int>("other"_hs));
+    ASSERT_EQ(ctx.at<int>("other"_hs), 3);
+
+    ASSERT_TRUE(ctx.erase<int>("other"_hs));
+
+    ASSERT_FALSE(cctx.contains<int>("other"_hs));
+    ASSERT_EQ(ctx.find<int>("other"_hs), nullptr);
+}
+
 TEST(Registry, ContextAsRef) {
     entt::registry registry;
     int value{3};