meta: meta_func_node is no longer static
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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
|
||||
|
||||
/**
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user