From f86bc31cbbeeb30995eeae5bbe8a7c876d5b767b Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Mon, 13 Sep 2021 16:34:57 +0200 Subject: [PATCH] meta: shared lookup function to avoid unnecessary casts when searching for a meta constructor --- src/entt/meta/factory.hpp | 18 +++------- src/entt/meta/meta.hpp | 71 ++++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 48 deletions(-) diff --git a/src/entt/meta/factory.hpp b/src/entt/meta/factory.hpp index 0ca6509eb..a8d39ab31 100644 --- a/src/entt/meta/factory.hpp +++ b/src/entt/meta/factory.hpp @@ -174,20 +174,12 @@ class meta_factory { } 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.next = *it; - *it = &node; + + if(meta_range range{owner->func}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) { + node.next = owner->func; + owner->func = &node; + } } public: diff --git a/src/entt/meta/meta.hpp b/src/entt/meta/meta.hpp index 442321efa..542560de9 100644 --- a/src/entt/meta/meta.hpp +++ b/src/entt/meta/meta.hpp @@ -1050,6 +1050,38 @@ class meta_type { return nullptr; } + template + const auto * lookup(meta_any * const args, const typename internal::meta_type_node::size_type sz, Pred pred) const { + std::decay_t*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: /*! @brief Node type. */ using node_type = internal::meta_type_node; @@ -1288,15 +1320,8 @@ public: * @return A wrapper containing the new instance, if any. */ [[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. */ 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{}; } /**