meta: static local meta type node fallback

This commit is contained in:
skypjack
2025-09-15 14:45:31 +02:00
parent b400927f02
commit e9b3eee6d3
3 changed files with 49 additions and 42 deletions

View File

@@ -32,14 +32,18 @@ namespace internal {
class basic_meta_factory {
using invoke_type = std::remove_pointer_t<decltype(meta_func_node::invoke)>;
auto &fetch_node() noexcept {
return meta_context::from(*ctx).value[parent];
}
auto *find_member_or_assert() {
auto *member = find_member<&meta_data_node::id>(details->data, bucket);
auto *member = find_member<&meta_data_node::id>(fetch_node().details->data, bucket);
ENTT_ASSERT(member != nullptr, "Cannot find member");
return member;
}
auto *find_overload_or_assert() {
auto *overload = find_overload(find_member<&meta_func_node::id>(details->func, bucket), invoke);
auto *overload = find_overload(find_member<&meta_func_node::id>(fetch_node().details->func, bucket), invoke);
ENTT_ASSERT(overload != nullptr, "Cannot find overload");
return overload;
}
@@ -52,7 +56,7 @@ class basic_meta_factory {
protected:
void type(const id_type id, const char *name) noexcept {
reset_bucket(parent);
auto &&elem = meta_context::from(*ctx).value[parent];
auto &elem = fetch_node();
ENTT_ASSERT(elem.id == id || !resolve(*ctx, id), "Duplicate identifier");
elem.name = name;
elem.id = id;
@@ -60,36 +64,42 @@ protected:
template<typename Type>
void insert_or_assign(Type node) {
auto &elem = fetch_node();
reset_bucket(parent);
if constexpr(std::is_same_v<Type, meta_base_node>) {
auto *member = find_member<&meta_base_node::type>(details->base, node.type);
member ? (*member = node) : details->base.emplace_back(node);
auto *member = find_member<&meta_base_node::type>(elem.details->base, node.type);
member ? (*member = node) : elem.details->base.emplace_back(node);
} else if constexpr(std::is_same_v<Type, meta_conv_node>) {
auto *member = find_member<&meta_conv_node::type>(details->conv, node.type);
member ? (*member = node) : details->conv.emplace_back(node);
auto *member = find_member<&meta_conv_node::type>(elem.details->conv, node.type);
member ? (*member = node) : elem.details->conv.emplace_back(node);
} else {
static_assert(std::is_same_v<Type, meta_ctor_node>, "Unexpected type");
auto *member = find_member<&meta_ctor_node::id>(details->ctor, node.id);
member ? (*member = node) : details->ctor.emplace_back(node);
auto *member = find_member<&meta_ctor_node::id>(elem.details->ctor, node.id);
member ? (*member = node) : elem.details->ctor.emplace_back(node);
}
}
void data(meta_data_node node) {
auto &elem = fetch_node();
reset_bucket(node.id);
if(auto *member = find_member<&meta_data_node::id>(details->data, node.id); member == nullptr) {
details->data.emplace_back(std::move(node));
if(auto *member = find_member<&meta_data_node::id>(elem.details->data, node.id); member == nullptr) {
elem.details->data.emplace_back(std::move(node));
} else if(member->set != node.set || member->get != node.get) {
*member = std::move(node);
}
}
void func(meta_func_node node) {
auto &elem = fetch_node();
reset_bucket(node.id, node.invoke);
if(auto *member = find_member<&meta_func_node::id>(details->func, node.id); member == nullptr) {
details->func.emplace_back(std::move(node));
if(auto *member = find_member<&meta_func_node::id>(elem.details->func, node.id); member == nullptr) {
elem.details->func.emplace_back(std::move(node));
} else if(auto *overload = find_overload(member, node.invoke); overload == nullptr) {
while(member->next != nullptr) { member = member->next.get(); }
member->next = std::make_unique<meta_func_node>(std::move(node));
@@ -98,7 +108,7 @@ protected:
void traits(const meta_traits value) {
if(bucket == parent) {
meta_context::from(*ctx).value[bucket].traits |= value;
fetch_node().traits |= value;
} else if(invoke == nullptr) {
find_member_or_assert()->traits |= value;
} else {
@@ -108,7 +118,7 @@ protected:
void custom(meta_custom_node node) {
if(bucket == parent) {
details->custom = std::move(node);
fetch_node().details->custom = std::move(node);
} else if(invoke == nullptr) {
find_member_or_assert()->custom = std::move(node);
} else {
@@ -117,15 +127,12 @@ protected:
}
public:
basic_meta_factory(meta_ctx &area, meta_type_node node)
basic_meta_factory(meta_ctx &area, const meta_type_node &node)
: ctx{&area},
parent{node.info->hash()},
bucket{parent},
details{node.details.get()} {
if(details == nullptr) {
node.details = std::make_shared<meta_type_descriptor>();
meta_context::from(*ctx).value[parent] = node;
details = node.details.get();
bucket{parent} {
if(auto &curr = meta_context::from(*ctx).value.try_emplace(parent, node).first->second; curr.details == nullptr) {
curr.details = std::make_shared<meta_type_descriptor>();
}
}
@@ -134,7 +141,6 @@ private:
id_type parent{};
id_type bucket{};
invoke_type *invoke{};
meta_type_descriptor *details{};
};
} // namespace internal

View File

@@ -76,8 +76,8 @@ public:
private:
const meta_ctx *ctx{};
const void *data{};
internal::meta_type_node (*value_type_node)(const internal::meta_context &){};
internal::meta_type_node (*const_reference_node)(const internal::meta_context &){};
const internal::meta_type_node &(*value_type_node)(const internal::meta_context &){};
const internal::meta_type_node &(*const_reference_node)(const internal::meta_context &){};
size_type (*size_fn)(const void *){};
bool (*clear_fn)(void *){};
bool (*reserve_fn)(void *, const size_type){};
@@ -142,9 +142,9 @@ public:
private:
const meta_ctx *ctx{};
const void *data{};
internal::meta_type_node (*key_type_node)(const internal::meta_context &){};
internal::meta_type_node (*mapped_type_node)(const internal::meta_context &){};
internal::meta_type_node (*value_type_node)(const internal::meta_context &){};
const internal::meta_type_node &(*key_type_node)(const internal::meta_context &){};
const internal::meta_type_node &(*mapped_type_node)(const internal::meta_context &){};
const internal::meta_type_node &(*value_type_node)(const internal::meta_context &){};
size_type (*size_fn)(const void *){};
bool (*clear_fn)(void *){};
bool (*reserve_fn)(void *, const size_type){};
@@ -629,7 +629,7 @@ public:
private:
any storage;
const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
internal::meta_type_node (*resolve)(const internal::meta_context &) noexcept {};
const internal::meta_type_node &(*resolve)(const internal::meta_context &) noexcept {};
mutable internal::meta_type_node lazy_node{};
vtable_type *vtable{};
};

View File

@@ -69,7 +69,7 @@ struct meta_custom_node {
struct meta_base_node {
id_type type{};
meta_type_node (*resolve)(const meta_context &) noexcept {};
const meta_type_node &(*resolve)(const meta_context &) noexcept {};
const void *(*cast)(const void *) noexcept {};
};
@@ -94,7 +94,7 @@ struct meta_data_node {
const char *name{};
meta_traits traits{meta_traits::is_none};
size_type arity{0u};
meta_type_node (*type)(const meta_context &) noexcept {};
const meta_type_node &(*type)(const meta_context &) noexcept {};
meta_type (*arg)(const meta_ctx &, const size_type) noexcept {};
bool (*set)(meta_handle, meta_any){};
meta_any (*get)(meta_handle){};
@@ -108,7 +108,7 @@ struct meta_func_node {
const char *name{};
meta_traits traits{meta_traits::is_none};
size_type arity{0u};
meta_type_node (*ret)(const meta_context &) noexcept {};
const meta_type_node &(*ret)(const meta_context &) noexcept {};
meta_type (*arg)(const meta_ctx &, const size_type) noexcept {};
meta_any (*invoke)(meta_handle, meta_any *const){};
std::unique_ptr<meta_func_node> next;
@@ -119,8 +119,8 @@ struct meta_template_node {
using size_type = std::size_t;
size_type arity{0u};
meta_type_node (*resolve)(const meta_context &) noexcept {};
meta_type_node (*arg)(const meta_context &, const size_type) noexcept {};
const meta_type_node &(*resolve)(const meta_context &) noexcept {};
const meta_type_node &(*arg)(const meta_context &, const size_type) noexcept {};
};
struct meta_type_descriptor {
@@ -140,7 +140,7 @@ struct meta_type_node {
const char *name{};
meta_traits traits{meta_traits::is_none};
size_type size_of{0u};
meta_type_node (*remove_pointer)(const meta_context &) noexcept {};
const meta_type_node &(*remove_pointer)(const meta_context &) noexcept {};
meta_any (*default_constructor)(const meta_ctx &){};
double (*conversion_helper)(void *, const void *){};
meta_any (*from_void)(const meta_ctx &, void *, const void *){};
@@ -184,11 +184,11 @@ template<auto Member>
}
template<typename Type>
meta_type_node resolve(const meta_context &) noexcept;
const meta_type_node &resolve(const meta_context &) noexcept;
template<typename... Args>
[[nodiscard]] auto meta_arg_node(const meta_context &context, type_list<Args...>, [[maybe_unused]] const std::size_t index) noexcept {
meta_type_node (*value)(const meta_context &) noexcept = nullptr;
[[nodiscard]] const meta_type_node &meta_arg_node(const meta_context &context, type_list<Args...>, [[maybe_unused]] const std::size_t index) noexcept {
const meta_type_node &(*value)(const meta_context &) noexcept = nullptr;
if constexpr(sizeof...(Args) != 0u) {
std::size_t pos{};
@@ -294,7 +294,7 @@ auto setup_node_for() noexcept {
node.templ = meta_template_node{
meta_template_traits<Type>::args_type::size,
&resolve<typename meta_template_traits<Type>::class_type>,
+[](const meta_context &area, const std::size_t index) noexcept { return meta_arg_node(area, typename meta_template_traits<Type>::args_type{}, index); }};
+[](const meta_context &area, const std::size_t index) noexcept -> decltype(auto) { return meta_arg_node(area, typename meta_template_traits<Type>::args_type{}, index); }};
}
return node;
@@ -306,10 +306,11 @@ auto setup_node_for() noexcept {
}
template<typename Type>
[[nodiscard]] meta_type_node resolve(const meta_context &context) noexcept {
[[nodiscard]] const meta_type_node &resolve(const meta_context &context) noexcept {
static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");
const auto *elem = try_resolve(context, type_id<Type>());
return (elem == nullptr) ? setup_node_for<Type>() : *elem;
static const meta_type_node node = setup_node_for<Type>();
const auto *elem = try_resolve(context, *node.info);
return (elem == nullptr) ? node : *elem;
}
} // namespace internal