Skip to content

Commit

Permalink
meta: guaranteed order on overloaded meta functions
Browse files Browse the repository at this point in the history
  • Loading branch information
skypjack committed Jul 25, 2024
1 parent 5213692 commit 097cadc
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 33 deletions.
37 changes: 20 additions & 17 deletions src/entt/meta/factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,26 +74,29 @@ class basic_meta_factory {
}

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) {
Expand Down
60 changes: 44 additions & 16 deletions test/entt/meta/meta_type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,34 +71,26 @@ 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) {
return 2 * std::as_const(*this).f(v);
}

[[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{};
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down

0 comments on commit 097cadc

Please sign in to comment.