Ver código fonte

meta: meta_conv_node is no longer static

Michele Caini 3 anos atrás
pai
commit
7f9e200cfb

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

@@ -28,7 +28,9 @@ namespace internal {
 
 inline void link_prop_if_required(internal::meta_prop_node **ref, internal::meta_prop_node &node) noexcept {
     for(auto it = *ref; it; it = it->next) {
-        if(it == &node) { return; }
+        if(it == &node) {
+            return;
+        }
         ENTT_ASSERT(it->id != node.id, "Duplicate identifier");
     }
 
@@ -48,25 +50,20 @@ inline void link_type_if_required(meta_type_node *owner, const id_type id) noexc
 
 inline void link_base_if_required(meta_type_node *owner, meta_base_node &node) noexcept {
     for(auto it = owner->base; it; it = it->next) {
-        if(it == &node) { return; }
+        if(it == &node) {
+            return;
+        }
     }
 
     node.next = owner->base;
     owner->base = &node;
 }
 
-inline void link_conv_if_required(meta_type_node *owner, meta_conv_node &node) noexcept {
-    for(auto it = owner->conv; it; it = it->next) {
-        if(it == &node) { return; }
-    }
-
-    node.next = owner->conv;
-    owner->conv = &node;
-}
-
 inline void link_ctor_if_required(meta_type_node *owner, meta_ctor_node &node) noexcept {
     for(auto it = owner->ctor; it; it = it->next) {
-        if(it == &node) { return; }
+        if(it == &node) {
+            return;
+        }
     }
 
     node.next = owner->ctor;
@@ -87,7 +84,9 @@ inline void link_func_if_required(meta_type_node *owner, const id_type id, meta_
     node.id = id;
 
     for(auto it = owner->func; it; it = it->next) {
-        if(it == &node) { return; }
+        if(it == &node) {
+            return;
+        }
     }
 
     node.next = owner->func;
@@ -294,14 +293,13 @@ public:
      */
     template<auto Candidate>
     auto conv() noexcept {
-        static internal::meta_conv_node node{
-            nullptr,
-            internal::meta_node<std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<decltype(Candidate), Type &>>>>::resolve(),
-            [](const meta_any &instance) -> meta_any { return forward_as_meta(std::invoke(Candidate, *static_cast<const Type *>(instance.data()))); }
-            // tricks clang-format
-        };
+        using conv_type = std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<decltype(Candidate), Type &>>>;
+
+        owner->conv[type_id<conv_type>().hash()] = internal::meta_conv_node{
+            [](const meta_any &instance) -> meta_any {
+                return forward_as_meta(std::invoke(Candidate, *static_cast<const Type *>(instance.data())));
+            }};
 
-        internal::link_conv_if_required(owner, node);
         return meta_factory<Type>{};
     }
 
@@ -316,14 +314,13 @@ public:
      */
     template<typename To>
     auto conv() noexcept {
-        static internal::meta_conv_node node{
-            nullptr,
-            internal::meta_node<std::remove_cv_t<std::remove_reference_t<To>>>::resolve(),
-            [](const meta_any &instance) -> meta_any { return forward_as_meta(static_cast<To>(*static_cast<const Type *>(instance.data()))); }
-            // tricks clang-format
-        };
+        using conv_type = std::remove_cv_t<std::remove_reference_t<To>>;
+
+        owner->conv[type_id<conv_type>().hash()] = internal::meta_conv_node{
+            [](const meta_any &instance) -> meta_any {
+                return forward_as_meta(static_cast<To>(*static_cast<const Type *>(instance.data())));
+            }};
 
-        internal::link_conv_if_required(owner, node);
         return meta_factory<Type>{};
     }
 
@@ -631,12 +628,12 @@ inline void meta_reset(const id_type id) noexcept {
         if(auto *node = *it; node->id == id) {
             clear_chain(&node->prop);
             clear_chain(&node->base);
-            clear_chain(&node->conv);
             clear_chain(&node->ctor);
             clear_chain(&node->data, &internal::meta_data_node::prop);
             clear_chain(&node->func, &internal::meta_func_node::prop);
 
             node->id = {};
+            node->conv.clear();
             node->templ.reset();
             node->dtor = nullptr;
             *it = std::exchange(node->next, nullptr);

+ 3 - 5
src/entt/meta/meta.hpp

@@ -944,7 +944,7 @@ class meta_type {
                         ++direct;
                     } else {
                         ext += internal::find_by<&node_type::base>(info, type.node)
-                               || internal::find_by<&node_type::conv>(info, type.node)
+                               || type.node->conv.contains(info.hash())
                                || (type.node->conversion_helper && other.node->conversion_helper);
                     }
                 }
@@ -1398,10 +1398,8 @@ bool meta_any::set(const id_type id, Type &&value) {
     if(const auto &info = type.info(); node && *node->info == info) {
         return as_ref();
     } else if(node) {
-        for(auto *it = node->conv; it; it = it->next) {
-            if(*it->type->info == info) {
-                return it->conv(*this);
-            }
+        if(auto it = node->conv.find(info.hash()); it != node->conv.cend()) {
+            return it->second.conv(*this);
         }
 
         if(node->conversion_helper && (type.is_arithmetic() || type.is_enum())) {

+ 8 - 4
src/entt/meta/node.hpp

@@ -5,6 +5,7 @@
 #include <memory>
 #include <type_traits>
 #include <utility>
+#include "../container/dense_map.hpp"
 #include "../core/attribute.h"
 #include "../core/enum.hpp"
 #include "../core/fwd.hpp"
@@ -56,13 +57,12 @@ struct meta_base_node {
 };
 
 struct meta_conv_node {
-    meta_conv_node *next;
-    meta_type_node *const type;
-    meta_any (*const conv)(const meta_any &);
+    meta_any (*conv)(const meta_any &);
 };
 
 struct meta_ctor_node {
     using size_type = std::size_t;
+
     meta_ctor_node *next;
     const size_type arity;
     meta_type (*const arg)(const size_type) noexcept;
@@ -71,6 +71,7 @@ struct meta_ctor_node {
 
 struct meta_data_node {
     using size_type = std::size_t;
+
     id_type id;
     const meta_traits traits;
     meta_data_node *next;
@@ -84,6 +85,7 @@ struct meta_data_node {
 
 struct meta_func_node {
     using size_type = std::size_t;
+
     id_type id;
     const meta_traits traits;
     meta_func_node *next;
@@ -96,6 +98,7 @@ struct meta_func_node {
 
 struct meta_template_node {
     using size_type = std::size_t;
+
     size_type arity;
     meta_type_node *type;
     meta_type_node *(*arg)(const size_type) noexcept;
@@ -103,6 +106,7 @@ struct meta_template_node {
 
 struct meta_type_node {
     using size_type = std::size_t;
+
     const type_info *info;
     id_type id;
     const meta_traits traits;
@@ -116,7 +120,7 @@ struct meta_type_node {
     std::unique_ptr<meta_template_node> templ;
     meta_ctor_node *ctor{nullptr};
     meta_base_node *base{nullptr};
-    meta_conv_node *conv{nullptr};
+    dense_map<id_type, meta_conv_node, identity> conv{};
     meta_data_node *data{nullptr};
     meta_func_node *func{nullptr};
     void (*dtor)(void *){nullptr};

+ 2 - 4
test/entt/meta/meta_conv.cpp

@@ -64,8 +64,6 @@ TEST_F(MetaConv, ReRegistration) {
 
     auto *node = entt::internal::meta_node<clazz_t>::resolve();
 
-    ASSERT_NE(node->conv, nullptr);
-    ASSERT_NE(node->conv->next, nullptr);
-    ASSERT_NE(node->conv->next->next, nullptr);
-    ASSERT_EQ(node->conv->next->next->next, nullptr);
+    ASSERT_FALSE(node->conv.empty());
+    ASSERT_EQ(node->conv.size(), 3u);
 }