meta: guaranteed order on overloaded meta functions

This commit is contained in:
Michele Caini
2024-07-25 14:31:06 +02:00
committed by skypjack
parent a8118c9389
commit 689005d452
2 changed files with 64 additions and 33 deletions

View File

@@ -74,26 +74,29 @@ protected:
}
void func(const id_type id, meta_func_node node) {
if(auto it = details->func.find(id); it != details->func.end()) {
for(auto *curr = &it->second; curr; curr = curr->next.get()) {
if(curr->invoke == node.invoke) {
node.next = std::move(curr->next);
*curr = std::move(node);
bucket = &curr->prop;
user = &curr->custom;
mask = &curr->traits;
return;
}
if(auto it = details->func.find(id); it == details->func.end()) {
auto &&elem = details->func.insert_or_assign(id, std::move(node)).first;
bucket = &elem->second.prop;
user = &elem->second.custom;
mask = &elem->second.traits;
} else {
auto *curr = &it->second;
while(curr->invoke != node.invoke && curr->next) {
curr = curr->next.get();
}
// locally overloaded function
node.next = std::make_shared<meta_func_node>(std::move(details->func[id]));
}
if(curr->invoke != node.invoke) {
curr->next = std::make_shared<meta_func_node>();
curr = curr->next.get();
}
auto &&it = details->func.insert_or_assign(id, std::move(node)).first;
bucket = &it->second.prop;
user = &it->second.custom;
mask = &it->second.traits;
node.next = std::move(curr->next);
*curr = std::move(node);
bucket = &curr->prop;
user = &curr->custom;
mask = &curr->traits;
}
}
void prop(const id_type key, meta_prop_node value) {

View File

@@ -71,17 +71,13 @@ struct clazz {
};
struct overloaded_func {
[[nodiscard]] int e(int v) const {
return v + v;
}
[[nodiscard]] int f(const base &, int a, int b) {
return f(a, b);
}
[[nodiscard]] int f(int a, const int b) {
value = a;
return g(b);
return b * b;
}
[[nodiscard]] int f(int v) {
@@ -89,16 +85,12 @@ struct overloaded_func {
}
[[nodiscard]] int f(int v) const {
return g(v);
return v * v;
}
[[nodiscard]] float f(int a, const float b) {
value = a;
return static_cast<float>(e(static_cast<int>(b)));
}
[[nodiscard]] int g(int v) const {
return v * v;
return b + b;
}
int value{};
@@ -147,13 +139,11 @@ struct MetaType: ::testing::Test {
entt::meta<overloaded_func>()
.type("overloaded_func"_hs)
.func<&overloaded_func::e>("e"_hs)
.func<entt::overload<int(const base &, int, int)>(&overloaded_func::f)>("f"_hs)
.func<entt::overload<int(int, int)>(&overloaded_func::f)>("f"_hs)
.func<entt::overload<int(int)>(&overloaded_func::f)>("f"_hs)
.func<entt::overload<int(int) const>(&overloaded_func::f)>("f"_hs)
.func<entt::overload<float(int, float)>(&overloaded_func::f)>("f"_hs)
.func<&overloaded_func::g>("g"_hs);
.func<entt::overload<float(int, float)>(&overloaded_func::f)>("f"_hs);
entt::meta<property_type>()
.type("property"_hs)
@@ -457,8 +447,6 @@ TEST_F(MetaType, OverloadedFunc) {
entt::meta_any res{};
ASSERT_TRUE(type.func("f"_hs));
ASSERT_TRUE(type.func("e"_hs));
ASSERT_TRUE(type.func("g"_hs));
res = type.invoke("f"_hs, instance, base{}, 1, 2);
@@ -506,6 +494,46 @@ TEST_F(MetaType, OverloadedFunc) {
ASSERT_FALSE(type.invoke("f"_hs, instance, 4, 8.));
}
TEST_F(MetaType, OverloadedFuncOrder) {
using namespace entt::literals;
const auto type = entt::resolve<overloaded_func>();
auto func = type.func("f"_hs);
ASSERT_TRUE(func);
ASSERT_EQ(func.arity(), 3u);
ASSERT_FALSE(func.is_const());
ASSERT_EQ(func.ret(), entt::resolve<int>());
func = func.next();
ASSERT_TRUE(func);
ASSERT_EQ(func.arity(), 2u);
ASSERT_FALSE(func.is_const());
ASSERT_EQ(func.ret(), entt::resolve<int>());
func = func.next();
ASSERT_TRUE(func);
ASSERT_EQ(func.arity(), 1u);
ASSERT_FALSE(func.is_const());
ASSERT_EQ(func.ret(), entt::resolve<int>());
func = func.next();
ASSERT_TRUE(func);
ASSERT_EQ(func.arity(), 1u);
ASSERT_TRUE(func.is_const());
ASSERT_EQ(func.ret(), entt::resolve<int>());
func = func.next();
ASSERT_TRUE(func);
ASSERT_EQ(func.arity(), 2u);
ASSERT_FALSE(func.is_const());
ASSERT_EQ(func.ret(), entt::resolve<float>());
}
TEST_F(MetaType, Construct) {
auto any = entt::resolve<clazz>().construct(base{}, 2);