meta: meta_func_node is no longer static

This commit is contained in:
Michele Caini
2022-08-23 18:19:54 +02:00
parent 945e61d668
commit 53f2bb7701
4 changed files with 78 additions and 127 deletions

View File

@@ -36,19 +36,6 @@ inline void link_type_if_required(meta_type_node *owner, const id_type id) noexc
}
}
inline void link_func_if_required(meta_type_node *owner, const id_type id, meta_func_node &node) noexcept {
node.id = id;
for(auto it = owner->func; it; it = it->next) {
if(it == &node) {
return;
}
}
node.next = owner->func;
owner->func = &node;
}
} // namespace internal
/**
@@ -423,19 +410,30 @@ public:
using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy");
static internal::meta_func_node node{
{},
internal::meta_func_node node{
type_id<type_list_cat_t<type_list<descriptor::return_type>, descriptor::args_type>>().hash(),
(descriptor::is_const ? internal::meta_traits::is_const : internal::meta_traits::is_none) | (descriptor::is_static ? internal::meta_traits::is_static : internal::meta_traits::is_none),
nullptr,
descriptor::args_type::size,
internal::meta_node<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, std::remove_cv_t<std::remove_reference_t<typename descriptor::return_type>>>>::resolve(),
&meta_arg<typename descriptor::args_type>,
&meta_invoke<Type, Candidate, Policy>
// tricks clang-format
};
&meta_invoke<Type, Candidate, Policy>};
internal::link_func_if_required(owner, id, node);
return meta_factory<Type, decltype(internal::meta_func_node::prop)>{node.prop};
if(owner->func.contains(id)) {
for(auto *curr = &owner->func[id]; curr; curr = curr->next.get()) {
if(curr->watermark == node.watermark && curr->traits == node.traits) {
node.next = std::move(curr->next);
*curr = std::move(node);
return meta_factory<Type, decltype(internal::meta_func_node::prop)>{curr->prop};
}
}
// locally overloaded function
node.next = std::make_unique<internal::meta_func_node>(std::move(owner->func[id]));
}
owner->func[id] = std::move(node);
return meta_factory<Type, decltype(internal::meta_func_node::prop)>{owner->func[id].prop};
}
private:
@@ -474,16 +472,13 @@ template<typename Type>
inline void meta_reset(const id_type id) noexcept {
for(auto **it = internal::meta_context::global(); *it; it = &(*it)->next) {
if(auto *node = *it; node->id == id) {
for(auto **curr = &node->func; *curr; *curr = std::exchange((*curr)->next, nullptr)) {
(*curr)->prop.clear();
}
node->id = {};
node->prop.clear();
node->ctor.clear();
node->base.clear();
node->conv.clear();
node->data.clear();
node->func.clear();
node->dtor.dtor = nullptr;
*it = std::exchange(node->next, nullptr);

View File

@@ -804,11 +804,6 @@ struct meta_func {
meta_func(const node_type *curr = nullptr) noexcept
: node{curr} {}
/*! @copydoc meta_type::id */
[[nodiscard]] id_type id() const noexcept {
return node->id;
}
/**
* @brief Returns the number of arguments accepted by a member function.
* @return The number of arguments accepted by the member function.
@@ -898,6 +893,14 @@ struct meta_func {
return nullptr;
}
/**
* @brief Returns the next overload of a given function, if any.
* @return The next overload of the given function, if any.
*/
[[nodiscard]] meta_func next() const {
return node->next ? meta_func{node->next.get()} : meta_func{};
}
/**
* @brief Returns true if an object is valid, false otherwise.
* @return True if the object is valid, false otherwise.
@@ -912,52 +915,16 @@ private:
/*! @brief Opaque wrapper for types. */
class meta_type {
template<typename It>
[[nodiscard]] auto lookup(It begin, It end, meta_any *const args, const typename internal::meta_type_node::size_type sz) const {
size_type extent{sz + 1u};
bool ambiguous{};
auto candidate = end;
template<typename Func>
[[nodiscard]] auto lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, Func next) const {
using element_type = decltype(next());
for(; begin != end; ++begin) {
if(begin->second.arity == sz) {
size_type direct{};
size_type ext{};
for(size_type next{}; next < sz && next == (direct + ext) && args[next]; ++next) {
const auto type = args[next].type();
const auto other = begin->second.arg(next);
if(const auto &info = other.info(); info == type.info()) {
++direct;
} else {
ext += type.node->base.contains(info.hash()) || type.node->conv.contains(info.hash())
|| (type.node->conversion_helper && other.node->conversion_helper);
}
}
if((direct + ext) == sz) {
if(ext < extent) {
candidate = begin;
extent = ext;
ambiguous = false;
} else if(ext == extent) {
ambiguous = true;
}
}
}
}
return ambiguous ? end : candidate;
}
template<auto Member, typename... Check>
[[nodiscard]] std::decay_t<decltype(std::declval<internal::meta_type_node>().*Member)> old_lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, Check... check) const {
std::decay_t<decltype(node->*Member)> candidate{};
element_type candidate = nullptr;
size_type extent{sz + 1u};
bool ambiguous{};
for(auto *curr = (node->*Member); curr; curr = curr->next) {
if(((curr->id == check) && ... && (curr->arity == sz))) {
for(element_type curr = next(); curr; curr = next()) {
if(curr->arity == sz) {
size_type direct{};
size_type ext{};
@@ -985,7 +952,7 @@ class meta_type {
}
}
return (candidate && !ambiguous) ? candidate : decltype(candidate){};
return ambiguous ? nullptr : candidate;
}
public:
@@ -1202,8 +1169,8 @@ public:
* @brief Returns a range to visit registered top-level functions.
* @return An iterable range to visit registered top-level functions.
*/
[[nodiscard]] old_meta_range<meta_func> func() const noexcept {
return {node->func, nullptr};
[[nodiscard]] meta_range<meta_func, typename decltype(internal::meta_type_node::func)::const_iterator> func() const noexcept {
return {node->func.cbegin(), node->func.cend()};
}
/**
@@ -1217,7 +1184,17 @@ public:
* @return The registered meta function for the given identifier, if any.
*/
[[nodiscard]] meta_func func(const id_type id) const {
return internal::find_by<&node_type::func>(id, node);
if(auto it = node->func.find(id); it != node->func.cend()) {
return &it->second;
}
for(auto &&curr: base()) {
if(auto &&elem = curr.second.func(id); elem) {
return elem;
}
}
return meta_func{};
}
/**
@@ -1232,8 +1209,12 @@ public:
* @return A wrapper containing the new instance, if any.
*/
[[nodiscard]] meta_any construct(meta_any *const args, const size_type sz) const {
if(auto it = lookup(node->ctor.cbegin(), node->ctor.cend(), args, sz); it != node->ctor.cend()) {
return it->second.invoke(args);
const auto *candidate = lookup(args, sz, [first = node->ctor.cbegin(), last = node->ctor.cend()]() mutable {
return first == last ? nullptr : &(first++)->second;
});
if(candidate) {
return candidate->invoke(args);
}
return (sz == 0u && node->default_constructor) ? node->default_constructor() : meta_any{};
@@ -1283,8 +1264,14 @@ 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 {
if(const auto *candidate = old_lookup<&node_type::func>(args, sz, id); candidate) {
return candidate->invoke(std::move(instance), args);
if(auto it = node->func.find(id); it != node->func.cend()) {
const auto *candidate = lookup(args, sz, [curr = &it->second]() mutable {
return curr ? std::exchange(curr, curr->next.get()) : nullptr;
});
if(candidate) {
return candidate->invoke(std::move(instance), args);
}
}
for(auto &&curr: base()) {

View File

@@ -86,14 +86,14 @@ struct meta_data_node {
struct meta_func_node {
using size_type = std::size_t;
id_type id;
const meta_traits traits;
meta_func_node *next;
const size_type arity;
meta_type_node *const ret;
meta_type (*const arg)(const size_type) noexcept;
meta_any (*const invoke)(meta_handle, meta_any *const);
id_type watermark;
meta_traits traits;
size_type arity;
meta_type_node *ret;
meta_type (*arg)(const size_type) noexcept;
meta_any (*invoke)(meta_handle, meta_any *const);
dense_map<id_type, meta_prop_node, identity> prop{};
std::unique_ptr<meta_func_node> next{};
};
struct meta_template_node {
@@ -122,7 +122,7 @@ struct meta_type_node {
dense_map<id_type, meta_base_node, identity> base{};
dense_map<id_type, meta_conv_node, identity> conv{};
dense_map<id_type, meta_data_node, identity> data{};
meta_func_node *func{nullptr};
dense_map<id_type, meta_func_node, identity> func{};
meta_dtor_node dtor{};
};
@@ -213,33 +213,6 @@ template<typename... Args>
return args[index + 1u];
}
template<auto Member, typename Type>
[[nodiscard]] static std::decay_t<decltype(std::declval<internal::meta_type_node>().*Member)> find_by(const Type &info_or_id, const internal::meta_type_node *node) noexcept {
for(auto *curr = node->*Member; curr; curr = curr->next) {
if constexpr(std::is_same_v<Type, type_info>) {
if(*curr->type->info == info_or_id) {
return curr;
}
} else if constexpr(std::is_same_v<decltype(curr), meta_base_node *>) {
if(curr->type->id == info_or_id) {
return curr;
}
} else {
if(curr->id == info_or_id) {
return curr;
}
}
}
for(auto &&curr: node->base) {
if(auto *ret = find_by<Member>(info_or_id, curr.second.type); ret) {
return ret;
}
}
return nullptr;
}
} // namespace internal
/**

View File

@@ -139,13 +139,17 @@ struct MetaFunc: ::testing::Test {
std::size_t count = 0;
for(auto func: entt::resolve<func_t>().func()) {
count += static_cast<bool>(func);
for(auto curr = func.second; curr; curr = curr.next()) {
++count;
}
}
SetUp();
for(auto func: entt::resolve<func_t>().func()) {
count -= static_cast<bool>(func);
for(auto curr = func.second; curr; curr = curr.next()) {
--count;
}
}
return count;
@@ -161,7 +165,6 @@ TEST_F(MetaFunc, Functionalities) {
func_t instance{};
ASSERT_TRUE(func);
ASSERT_EQ(func.id(), "f2"_hs);
ASSERT_EQ(func.arity(), 2u);
ASSERT_FALSE(func.is_const());
ASSERT_FALSE(func.is_static());
@@ -200,7 +203,6 @@ TEST_F(MetaFunc, Const) {
func_t instance{};
ASSERT_TRUE(func);
ASSERT_EQ(func.id(), "f1"_hs);
ASSERT_EQ(func.arity(), 1u);
ASSERT_TRUE(func.is_const());
ASSERT_FALSE(func.is_static());
@@ -237,7 +239,6 @@ TEST_F(MetaFunc, RetVoid) {
func_t instance{};
ASSERT_TRUE(func);
ASSERT_EQ(func.id(), "g"_hs);
ASSERT_EQ(func.arity(), 1u);
ASSERT_FALSE(func.is_const());
ASSERT_FALSE(func.is_static());
@@ -272,7 +273,6 @@ TEST_F(MetaFunc, Static) {
func_t::value = 2;
ASSERT_TRUE(func);
ASSERT_EQ(func.id(), "h"_hs);
ASSERT_EQ(func.arity(), 1u);
ASSERT_FALSE(func.is_const());
ASSERT_TRUE(func.is_static());
@@ -308,7 +308,6 @@ TEST_F(MetaFunc, StaticRetVoid) {
auto func = entt::resolve<func_t>().func("k"_hs);
ASSERT_TRUE(func);
ASSERT_EQ(func.id(), "k"_hs);
ASSERT_EQ(func.arity(), 1u);
ASSERT_FALSE(func.is_const());
ASSERT_TRUE(func.is_static());
@@ -344,7 +343,6 @@ TEST_F(MetaFunc, StaticAsMember) {
auto any = func.invoke(instance, 42);
ASSERT_TRUE(func);
ASSERT_EQ(func.id(), "fake_member"_hs);
ASSERT_EQ(func.arity(), 1u);
ASSERT_FALSE(func.is_const());
ASSERT_FALSE(func.is_static());
@@ -368,7 +366,6 @@ TEST_F(MetaFunc, StaticAsConstMember) {
auto any = func.invoke(std::as_const(instance));
ASSERT_TRUE(func);
ASSERT_EQ(func.id(), "fake_const_member"_hs);
ASSERT_EQ(func.arity(), 0u);
ASSERT_TRUE(func.is_const());
ASSERT_FALSE(func.is_static());
@@ -558,7 +555,6 @@ TEST_F(MetaFunc, ExternalMemberFunction) {
auto func = entt::resolve<func_t>().func("emplace"_hs);
ASSERT_TRUE(func);
ASSERT_EQ(func.id(), "emplace"_hs);
ASSERT_EQ(func.arity(), 2u);
ASSERT_FALSE(func.is_const());
ASSERT_TRUE(func.is_static());
@@ -597,8 +593,8 @@ TEST_F(MetaFunc, ReRegistration) {
.func<entt::overload<int(int, int)>(&func_t::f)>("f"_hs)
.func<entt::overload<int(int) const>(&func_t::f)>("f"_hs);
ASSERT_FALSE(type.func("f1"_hs));
ASSERT_FALSE(type.func("f2"_hs));
ASSERT_TRUE(type.func("f1"_hs));
ASSERT_TRUE(type.func("f2"_hs));
ASSERT_TRUE(type.func("f"_hs));
ASSERT_TRUE(type.invoke("f"_hs, instance, 0));