Przeglądaj źródła

meta: shared lookup function to avoid unnecessary casts when searching for a meta constructor

Michele Caini 4 lat temu
rodzic
commit
f86bc31cbb
2 zmienionych plików z 41 dodań i 48 usunięć
  1. 5 13
      src/entt/meta/factory.hpp
  2. 36 35
      src/entt/meta/meta.hpp

+ 5 - 13
src/entt/meta/factory.hpp

@@ -174,20 +174,12 @@ class meta_factory<Type> {
     }
     }
 
 
     void link_func_if_required(const id_type id, internal::meta_func_node &node) {
     void link_func_if_required(const id_type id, internal::meta_func_node &node) {
-        for(auto *it = &owner->func; *it; it = &(*it)->next) {
-            if(*it == &node) {
-                *it = node.next;
-                break;
-            }
-        }
-
-        internal::meta_func_node **it = &owner->func;
-        for(; *it && (*it)->id != id; it = &(*it)->next);
-        for(; *it && (*it)->id == id && (*it)->arity < node.arity; it = &(*it)->next);
-
         node.id = id;
         node.id = id;
-        node.next = *it;
-        *it = &node;
+
+        if(meta_range<internal::meta_func_node *, internal::meta_func_node> range{owner->func}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
+            node.next = owner->func;
+            owner->func = &node;
+        }
     }
     }
 
 
 public:
 public:

+ 36 - 35
src/entt/meta/meta.hpp

@@ -1050,6 +1050,38 @@ class meta_type {
         return nullptr;
         return nullptr;
     }
     }
 
 
+    template<auto Member, typename Pred>
+    const auto * lookup(meta_any * const args, const typename internal::meta_type_node::size_type sz, Pred pred) const {
+        std::decay_t<decltype(node->*Member)> candidate{};
+        size_type extent{sz + 1u};
+        bool ambiguous{};
+
+        for(auto *curr = (node->*Member); curr; curr = curr->next) {
+            if(pred(curr) && curr->arity == sz) {
+                size_type direct{};
+                size_type ext{};
+
+                for(size_type next{}; next < sz && next == (direct + ext); ++next) {
+                    const auto type = args[next].type();
+                    const auto other = curr->arg(next);
+                    type.info() == other.info() ? ++direct : (ext += internal::can_cast_or_convert(type.node, other.node));
+                }
+
+                if((direct + ext) == sz) {
+                    if(ext < extent) {
+                        candidate = curr;
+                        extent = ext;
+                        ambiguous = false;
+                    } else if(ext == extent) {
+                        ambiguous = true;
+                    }
+                }
+            }
+        }
+
+        return (candidate && !ambiguous) ? candidate : decltype(candidate){};
+    }
+
 public:
 public:
     /*! @brief Node type. */
     /*! @brief Node type. */
     using node_type = internal::meta_type_node;
     using node_type = internal::meta_type_node;
@@ -1288,15 +1320,8 @@ public:
      * @return A wrapper containing the new instance, if any.
      * @return A wrapper containing the new instance, if any.
      */
      */
     [[nodiscard]] meta_any construct(meta_any * const args, const size_type sz) const {
     [[nodiscard]] meta_any construct(meta_any * const args, const size_type sz) const {
-        for(auto *curr = node->ctor; curr; curr = curr->next) {
-            if(curr->arity == sz) {
-                if(auto ret = curr->invoke(args); ret) {
-                    return ret;
-                }
-            }
-        }
-
-        return (!sz && node->default_constructor) ? node->default_constructor() : meta_any{};
+        const auto *candidate = lookup<&node_type::ctor>(args, sz, [](const auto *) { return true; });
+        return candidate ? candidate->invoke(args) : ((!sz && node->default_constructor) ? node->default_constructor() : meta_any{});
     }
     }
 
 
     /**
     /**
@@ -1330,32 +1355,8 @@ public:
      * @return A wrapper containing the returned value, if any.
      * @return A wrapper containing the returned value, if any.
      */
      */
     meta_any invoke(const id_type id, meta_handle instance, meta_any * const args, const size_type sz) const {
     meta_any invoke(const id_type id, meta_handle instance, meta_any * const args, const size_type sz) const {
-        const internal::meta_func_node* candidate{};
-        size_type extent{sz + 1u};
-        bool ambiguous{};
-
-        for(auto *it = internal::visit<&node_type::func>([id, sz](const auto *curr) { return curr->id == id && curr->arity == sz; }, node); it && it->id == id && it->arity == sz; it = it->next) {
-            size_type direct{};
-            size_type ext{};
-
-            for(size_type next{}; next < sz && next == (direct + ext); ++next) {
-                const auto type = args[next].type();
-                const auto other = it->arg(next);
-                type.info() == other.info() ? ++direct : (ext += internal::can_cast_or_convert(type.node, other.node));
-            }
-
-            if((direct + ext) == sz) {
-                if(ext < extent) {
-                    candidate = it;
-                    extent = ext;
-                    ambiguous = false;
-                } else if(ext == extent) {
-                    ambiguous = true;
-                }
-            }
-        }
-
-        return (candidate && !ambiguous) ? candidate->invoke(std::move(instance), args) : meta_any{};
+        const auto *candidate = lookup<&node_type::func>(args, sz, [id](const auto *curr) { return curr->id == id; });
+        return candidate ? candidate->invoke(std::move(instance), args) : meta_any{};
     }
     }
 
 
     /**
     /**