浏览代码

meta: uses type_id_v rather than other techniques

Michele Caini 6 年之前
父节点
当前提交
acb70d4440
共有 8 个文件被更改,包括 49 次插入72 次删除
  1. 0 2
      TODO
  2. 7 25
      src/entt/meta/factory.hpp
  3. 22 25
      src/entt/meta/meta.hpp
  4. 3 3
      test/entt/meta/meta.cpp
  5. 4 1
      test/lib/meta/lib.cpp
  6. 10 5
      test/lib/meta/main.cpp
  7. 3 6
      test/plugin/meta/main.cpp
  8. 0 5
      test/plugin/meta/plugin.cpp

+ 0 - 2
TODO

@@ -27,8 +27,6 @@
 * Mission: get rid of named types
   - make it possible to use custom generators (eg for plugins)
     * ENTT_ID_TYPE id() (eg dispatcher) can be a data member rather than a virtual function
-    * meta: use type_id, remove import, everything should work transparently
-    * type_id_enabled and fallback on old-fashioned families otherwise
     * add discard pool functionality (+ test)
   - use type_id also for groups, get rid of extent and subfunctions, is it possible?
   - update doc: dispatcher, emitter, registry, meta, across boundaries

+ 7 - 25
src/entt/meta/factory.hpp

@@ -391,11 +391,11 @@ public:
     auto type(const ENTT_ID_TYPE identifier) ENTT_NOEXCEPT {
         auto * const node = internal::meta_info<Type>::resolve();
 
-        ENTT_ASSERT(!exists(identifier, *internal::meta_info<>::context()));
-        ENTT_ASSERT(!exists(node, *internal::meta_info<>::context()));
+        ENTT_ASSERT(!exists(identifier, *internal::meta_info<>::global));
+        ENTT_ASSERT(!exists(node, *internal::meta_info<>::global));
         node->identifier = identifier;
-        node->next = *internal::meta_info<>::context();
-        *internal::meta_info<>::context() = node;
+        node->next = *internal::meta_info<>::global;
+        *internal::meta_info<>::global = node;
 
         return meta_factory<Type, Type>{&node->prop};
     }
@@ -777,7 +777,7 @@ public:
      */
     auto reset() ENTT_NOEXCEPT {
         auto * const node = internal::meta_info<Type>::resolve();
-        auto **it = internal::meta_info<>::context();
+        auto **it = internal::meta_info<>::global;
 
         while(*it && *it != node) {
             it = &(*it)->next;
@@ -811,24 +811,6 @@ public:
 
         return meta_factory<Type, Type>{&node->prop};
     }
-
-    /**
-     * @brief Imports a meta type from another context.
-     * @param identifier Unique identifier.
-     * @return An extended meta factory for the given type.
-     */
-    auto import(const ENTT_ID_TYPE identifier) ENTT_NOEXCEPT {
-        auto * const ctx = *internal::meta_info<>::context();
-
-        ENTT_ASSERT(exists(identifier, ctx));
-        ENTT_ASSERT(!exists(internal::meta_info<Type>::resolve(), ctx));
-
-        internal::meta_info<Type>::alias = internal::find_if([identifier](const auto *curr) {
-            return curr->identifier == identifier;
-        }, ctx);
-
-        return meta_factory<Type, Type>{&internal::meta_info<Type>::resolve()->prop};
-    }
 };
 
 
@@ -870,7 +852,7 @@ inline meta_type resolve() ENTT_NOEXCEPT {
 inline meta_type resolve(const ENTT_ID_TYPE identifier) ENTT_NOEXCEPT {
     return internal::find_if([identifier](const auto *curr) {
         return curr->identifier == identifier;
-    }, *internal::meta_info<>::context());
+    }, *internal::meta_info<>::global);
 }
 
 
@@ -882,7 +864,7 @@ inline meta_type resolve(const ENTT_ID_TYPE identifier) ENTT_NOEXCEPT {
 template<typename Op>
 inline std::enable_if_t<std::is_invocable_v<Op, meta_type>, void>
 resolve(Op op) {
-    internal::visit<meta_type>(std::move(op), *internal::meta_info<>::context());
+    internal::visit<meta_type>(std::move(op), *internal::meta_info<>::global);
 }
 
 

+ 22 - 25
src/entt/meta/meta.hpp

@@ -7,7 +7,7 @@
 #include <functional>
 #include <type_traits>
 #include "../config/config.h"
-#include "../core/attribute.h"
+#include "../core/type_info.hpp"
 #include "../core/type_traits.hpp"
 
 
@@ -100,6 +100,7 @@ struct meta_func_node {
 
 struct meta_type_node {
     using size_type = std::size_t;
+    const ENTT_ID_TYPE id;
     ENTT_ID_TYPE identifier;
     meta_type_node * next;
     meta_prop_node * prop;
@@ -190,12 +191,12 @@ bool compare(const void *lhs, const void *rhs) {
 
 
 template<typename... Type>
-struct ENTT_API meta_node {
+struct meta_node {
     static_assert(std::is_same_v<Type..., std::remove_cv_t<std::remove_reference_t<Type>>...>);
-    inline static meta_type_node *alias = nullptr;
 
     inline static meta_type_node * resolve() ENTT_NOEXCEPT {
         static meta_type_node node{
+            type_id_v<Type...>,
             {},
             nullptr,
             nullptr,
@@ -216,19 +217,15 @@ struct ENTT_API meta_node {
             &meta_node<std::remove_const_t<std::remove_extent_t<Type>>...>::resolve
         };
 
-        return alias ? alias : &node;
+        return &node;
     }
 };
 
 
 template<>
-struct ENTT_API meta_node<> {
-    inline static meta_type_node **shared = nullptr;
-
-    inline static meta_type_node ** context() ENTT_NOEXCEPT {
-        static meta_type_node *local = nullptr;
-        return shared ? shared : &local;
-    }
+struct meta_node<> {
+    inline static meta_type_node *local = nullptr;
+    inline static meta_type_node **global = &local;
 };
 
 
@@ -252,12 +249,11 @@ struct meta_ctx {
      * @param other A valid context to which to bind.
      */
     static void bind(meta_ctx other) ENTT_NOEXCEPT {
-        ENTT_ASSERT(!internal::meta_info<>::shared);
-        internal::meta_info<>::shared = other.ctx;
+        internal::meta_info<>::global = other.ctx;
     }
 
 private:
-    internal::meta_type_node **ctx{internal::meta_info<>::context()};
+    internal::meta_type_node **ctx{&internal::meta_info<>::local};
 };
 
 
@@ -464,9 +460,9 @@ public:
     const Type * try_cast() const {
         void *ret = nullptr;
 
-        if(const auto * const type = internal::meta_info<Type>::resolve(); type == node) {
+        if(const auto id = internal::meta_info<Type>::resolve()->id; node && node->id == id) {
             ret = instance;
-        } else if(const auto *base = internal::find_if<&internal::meta_type_node::base>([type](const auto *curr) { return curr->type() == type; }, node); base) {
+        } else if(const auto *base = internal::find_if<&internal::meta_type_node::base>([id](const auto *curr) { return curr->type()->id == id; }, node); base) {
             ret = base->cast(instance);
         }
 
@@ -516,9 +512,9 @@ public:
     meta_any convert() const {
         meta_any any{};
 
-        if(const auto * const type = internal::meta_info<Type>::resolve(); node == type) {
+        if(const auto id = internal::meta_info<Type>::resolve()->id; node && node->id == id) {
             any = *static_cast<const Type *>(instance);
-        } else if(const auto * const conv = internal::find_if<&internal::meta_type_node::conv>([type](const auto *curr) { return curr->type() == type; }, node); conv) {
+        } else if(const auto * const conv = internal::find_if<&internal::meta_type_node::conv>([id](const auto *curr) { return curr->type()->id == id; }, node); conv) {
             any = conv->conv(instance);
         }
 
@@ -532,7 +528,7 @@ public:
      */
     template<typename Type>
     bool convert() {
-        bool valid = (node == internal::meta_info<Type>::resolve());
+        bool valid = (node && node->id == internal::meta_info<Type>::resolve()->id);
 
         if(!valid) {
             if(auto any = std::as_const(*this).convert<Type>(); (valid = static_cast<bool>(any))) {
@@ -578,7 +574,7 @@ public:
      * otherwise.
      */
     bool operator==(const meta_any &other) const {
-        return node == other.node && (!node || node->compare(instance, other.instance));
+        return (!node && !other.node) || (node && other.node && node->id == other.node->id && node->compare(instance, other.instance));
     }
 
     /**
@@ -1115,8 +1111,9 @@ class meta_type {
     auto ctor(std::index_sequence<Indexes...>) const {
         return internal::find_if([](const auto *candidate) {
             return candidate->size == sizeof...(Args) && ([](auto *from, auto *to) {
-                return (from == to) || internal::find_if<&internal::meta_type_node::base>([to](const auto *curr) { return curr->type() == to; }, from)
-                        || internal::find_if<&internal::meta_type_node::conv>([to](const auto *curr) { return curr->type() == to; }, from);
+                return (from->id == to->id)
+                        || internal::find_if<&internal::meta_type_node::base>([to](const auto *curr) { return curr->type()->id == to->id; }, from)
+                        || internal::find_if<&internal::meta_type_node::conv>([to](const auto *curr) { return curr->type()->id == to->id; }, from);
             }(internal::meta_info<Args>::resolve(), candidate->arg(Indexes)) && ...);
         }, node->ctor);
     }
@@ -1304,8 +1301,8 @@ public:
      */
     template<typename Type>
     meta_conv conv() const {
-        return internal::find_if<&internal::meta_type_node::conv>([type = internal::meta_info<Type>::resolve()](const auto *curr) {
-            return curr->type() == type;
+        return internal::find_if<&internal::meta_type_node::conv>([id = internal::meta_info<Type>::resolve()->id](const auto *curr) {
+            return curr->type()->id == id;
         }, node);
     }
 
@@ -1459,7 +1456,7 @@ public:
      * otherwise.
      */
     bool operator==(const meta_type &other) const ENTT_NOEXCEPT {
-        return node == other.node;
+        return (!node && !other.node) || (node && other.node && node->id == other.node->id);
     }
 
 private:

+ 3 - 3
test/entt/meta/meta.cpp

@@ -1903,7 +1903,7 @@ TEST_F(Meta, PropertiesAndCornerCases) {
 }
 
 TEST_F(Meta, Reset) {
-    ASSERT_NE(*entt::internal::meta_info<>::context(), nullptr);
+    ASSERT_NE(*entt::internal::meta_info<>::global, nullptr);
 
     entt::meta<char>().reset();
     entt::meta<concrete_type>().reset();
@@ -1921,7 +1921,7 @@ TEST_F(Meta, Reset) {
     entt::meta<another_abstract_type>().reset();
     entt::meta<unsigned int>().reset();
 
-    ASSERT_EQ(*entt::internal::meta_info<>::context(), nullptr);
+    ASSERT_EQ(*entt::internal::meta_info<>::global, nullptr);
 
     ASSERT_FALSE(entt::resolve("char"_hs));
     ASSERT_FALSE(entt::resolve("base"_hs));
@@ -1935,7 +1935,7 @@ TEST_F(Meta, Reset) {
     ASSERT_FALSE(entt::resolve("another_abstract_type"_hs));
     ASSERT_FALSE(entt::resolve("concrete"_hs));
 
-    ASSERT_EQ(*entt::internal::meta_info<>::context(), nullptr);
+    ASSERT_EQ(*entt::internal::meta_info<>::global, nullptr);
 
     Meta::SetUpAfterUnregistration();
     entt::meta_any any{42.};

+ 4 - 1
test/lib/meta/lib.cpp

@@ -8,7 +8,9 @@ position create_position(int x, int y) {
     return position{x, y};
 }
 
-ENTT_API void set_up() {
+ENTT_API void set_up(entt::meta_ctx ctx) {
+    entt::meta_ctx::bind(ctx);
+
     entt::meta<position>()
             .type("position"_hs)
             .ctor<&create_position>()
@@ -16,6 +18,7 @@ ENTT_API void set_up() {
             .data<&position::y>("y"_hs);
 
     entt::meta<velocity>()
+            .type("velocity"_hs)
             .ctor<>()
             .data<&velocity::dx>("dx"_hs)
             .data<&velocity::dy>("dy"_hs);

+ 10 - 5
test/lib/meta/main.cpp

@@ -4,20 +4,21 @@
 #include <entt/meta/meta.hpp>
 #include "types.h"
 
-ENTT_API void set_up();
+ENTT_API void set_up(entt::meta_ctx);
 ENTT_API void tear_down();
 ENTT_API entt::meta_any wrap_int(int);
 
 TEST(Lib, Meta) {
     ASSERT_FALSE(entt::resolve("position"_hs));
 
-    set_up();
+    set_up(entt::meta_ctx{});
     entt::meta<double>().conv<int>();
 
     ASSERT_TRUE(entt::resolve("position"_hs));
+    ASSERT_TRUE(entt::resolve("velocity"_hs));
 
     auto pos = entt::resolve("position"_hs).construct(42., 3.);
-    auto vel = entt::resolve<velocity>().ctor().invoke();
+    auto vel = entt::resolve("velocity"_hs).ctor().invoke();
 
     ASSERT_TRUE(pos && vel);
 
@@ -27,11 +28,15 @@ TEST(Lib, Meta) {
     ASSERT_EQ(pos.type().data("y"_hs).get(*pos).cast<int>(), 3);
 
     ASSERT_EQ(vel.type().data("dx"_hs).type(), entt::resolve<double>());
-    ASSERT_TRUE(vel.type().data("dy"_hs).get(*vel).convert<int>());
+    ASSERT_TRUE(vel.type().data("dy"_hs).get(*vel).convert<double>());
     ASSERT_EQ(vel.type().data("dx"_hs).get(*vel).cast<double>(), 0.);
     ASSERT_EQ(vel.type().data("dy"_hs).get(*vel).cast<double>(), 0.);
 
-    ASSERT_EQ(wrap_int(1).type(), entt::resolve<int>());
+    ASSERT_EQ(wrap_int(42).type(), entt::resolve<int>());
+    ASSERT_EQ(wrap_int(42).cast<int>(), 42);
 
     tear_down();
+
+    ASSERT_FALSE(entt::resolve("position"_hs));
+    ASSERT_FALSE(entt::resolve("velocity"_hs));
 }

+ 3 - 6
test/plugin/meta/main.cpp

@@ -7,11 +7,7 @@
 #include "types.h"
 
 TEST(Lib, Meta) {
-    entt::meta<double>().type("double"_hs);
-    entt::meta<int>().type("int"_hs);
-
     ASSERT_FALSE(entt::resolve("position"_hs));
-    ASSERT_FALSE(entt::resolve<double>().conv<int>());
 
     userdata ud{};
 
@@ -20,9 +16,10 @@ TEST(Lib, Meta) {
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_update(ctx);
 
+    entt::meta<double>().conv<int>();
+
     ASSERT_TRUE(entt::resolve("position"_hs));
     ASSERT_TRUE(entt::resolve("velocity"_hs));
-    ASSERT_TRUE(entt::resolve<double>().conv<int>());
 
     auto pos = entt::resolve("position"_hs).construct(42., 3.);
     auto vel = entt::resolve("velocity"_hs).ctor().invoke();
@@ -35,7 +32,7 @@ TEST(Lib, Meta) {
     ASSERT_EQ(pos.type().data("y"_hs).get(*pos).cast<int>(), 3);
 
     ASSERT_EQ(vel.type().data("dx"_hs).type(), entt::resolve<double>());
-    ASSERT_TRUE(vel.type().data("dy"_hs).get(*vel).convert<int>());
+    ASSERT_TRUE(vel.type().data("dy"_hs).get(*vel).convert<double>());
     ASSERT_EQ(vel.type().data("dx"_hs).get(*vel).cast<double>(), 0.);
     ASSERT_EQ(vel.type().data("dy"_hs).get(*vel).cast<double>(), 0.);
 

+ 0 - 5
test/plugin/meta/plugin.cpp

@@ -9,11 +9,6 @@ position create_position(int x, int y) {
 }
 
 void set_up() {
-    entt::meta<double>().import("double"_hs);
-    entt::meta<int>().import("int"_hs);
-
-    entt::meta<double>().conv<int>();
-
     entt::meta<position>()
             .type("position"_hs)
             .ctor<&create_position>()