meta: top-level only searches for data and functions

This commit is contained in:
skypjack
2025-10-31 11:36:26 +01:00
parent f3fa359edf
commit 31d5d5ff1c
4 changed files with 41 additions and 10 deletions

2
TODO
View File

@@ -36,4 +36,4 @@ TODO:
* find a way to test deleter and the absence of it in basic_any
* archetype-like a-là EnTT support (see my own notes)
* meta_factory: add a replace flag to traits to get around the |-only mechanism
* support searching meta data and func only on top level types, no bases
* propagate already loaded meta types from invoke/arg/whatever as much as possible to reduce lookups

View File

@@ -1324,10 +1324,11 @@ public:
/**
* @brief Lookup utility for meta data (bases are also visited).
* @param id Unique identifier.
* @param recursive True for a search in the base classes, false otherwise.
* @return The registered meta data for the given identifier, if any.
*/
[[nodiscard]] meta_data data(const id_type id) const {
const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), fetch_node(), id);
[[nodiscard]] meta_data data(const id_type id, const bool recursive = true) const {
const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), fetch_node(), id, recursive);
return (elem != nullptr) ? meta_data{*ctx, *elem} : meta_data{};
}
@@ -1343,10 +1344,11 @@ public:
/**
* @brief Lookup utility for meta functions (bases are also visited).
* @param id Unique identifier.
* @param recursive True for a search in the base classes, false otherwise.
* @return The registered meta function for the given identifier, if any.
*/
[[nodiscard]] meta_func func(const id_type id) const {
const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), fetch_node(), id);
[[nodiscard]] meta_func func(const id_type id, const bool recursive = true) const {
const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), fetch_node(), id, recursive);
return (elem != nullptr) ? meta_func{*ctx, *elem} : meta_func{};
}

View File

@@ -166,7 +166,7 @@ template<auto Member, typename Type, typename Value>
}
template<auto Member>
[[nodiscard]] auto *look_for(const meta_context &context, const meta_type_node &node, const id_type id) {
[[nodiscard]] auto *look_for(const meta_context &context, const meta_type_node &node, const id_type id, bool recursive) {
using value_type = typename std::remove_reference_t<decltype((node.details.get()->*Member))>::value_type;
if(node.details) {
@@ -174,9 +174,11 @@ template<auto Member>
return member;
}
for(auto &&curr: node.details->base) {
if(auto *elem = look_for<Member>(context, curr.resolve(context), id); elem) {
return elem;
if(recursive) {
for(auto &&curr: node.details->base) {
if(auto *elem = look_for<Member>(context, curr.resolve(context), id, recursive); elem) {
return elem;
}
}
}
}

View File

@@ -32,6 +32,10 @@ Type get(Type &elem) {
struct base {
char value{'c'};
static int f() {
return 0;
}
};
struct derived: base {
@@ -134,7 +138,8 @@ struct MetaType: ::testing::Test {
entt::meta_factory<base>{}
.type("base"_hs)
.data<&base::value>("value"_hs);
.data<&base::value>("value"_hs)
.func<&base::f>("func"_hs);
entt::meta_factory<derived>{}
.type("derived")
@@ -455,6 +460,17 @@ TEST_F(MetaType, Data) {
ASSERT_EQ(type.data().cbegin(), type.data().cend());
}
TEST_F(MetaType, DataRecursive) {
using namespace entt::literals;
auto type = entt::resolve<derived>();
const derived instance{};
ASSERT_TRUE(type.data("value"_hs));
ASSERT_EQ('c', type.data("value"_hs).get(instance).cast<char>());
ASSERT_FALSE(type.data("value"_hs, false));
}
TEST_F(MetaType, Func) {
using namespace entt::literals;
@@ -478,6 +494,17 @@ TEST_F(MetaType, Func) {
ASSERT_EQ(type.func().cbegin(), type.func().cend());
}
TEST_F(MetaType, FuncRecursive) {
using namespace entt::literals;
auto type = entt::resolve<derived>();
const derived instance{};
ASSERT_TRUE(type.func("func"_hs));
ASSERT_EQ(0, type.func("func"_hs).invoke(instance).cast<int>());
ASSERT_FALSE(type.func("func"_hs, false));
}
TEST_F(MetaType, Invoke) {
using namespace entt::literals;