meta: reduce the size of instantiated symbols in meta_factory

This commit is contained in:
Michele Caini
2021-09-13 11:43:06 +02:00
parent f26fa92d47
commit 00dadfe14d

View File

@@ -30,7 +30,7 @@ namespace entt {
* there are no subtle errors at runtime.
*/
template<typename...>
struct meta_factory;
class meta_factory;
/**
@@ -39,8 +39,15 @@ struct meta_factory;
* @tparam Spec Property specialization pack used to disambiguate overloads.
*/
template<typename Type, typename... Spec>
struct meta_factory<Type, Spec...>: public meta_factory<Type> {
private:
class meta_factory<Type, Spec...>: public meta_factory<Type> {
void link_prop_if_required(internal::meta_prop_node &node, const meta_any &instance) {
if(meta_range<internal::meta_prop_node *, internal::meta_prop_node> range{*ref}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [&instance](const auto *curr) { return curr->id == instance; }) == range.cend(), "Duplicate identifier");
node.next = *ref;
*ref = &node;
}
}
template<std::size_t Step = 0, typename... Property, typename... Other>
void unroll(choice_t<2>, std::tuple<Property...> property, Other &&... other) {
std::apply([this](auto &&... curr) { (unroll<Step>(choice<2>, std::forward<Property>(curr)), ...); }, property);
@@ -62,8 +69,8 @@ private:
template<std::size_t>
void unroll(choice_t<0>) {}
template<std::size_t = 0, typename Key>
void assign(Key &&key, meta_any value = {}) {
template<std::size_t = 0>
void assign(meta_any key, meta_any value = {}) {
static meta_any property[2u]{};
static internal::meta_prop_node node{
@@ -72,15 +79,9 @@ private:
property[1u]
};
meta_any instance{std::forward<Key>(key)};
property[0u] = std::move(instance);
property[0u] = std::move(key);
property[1u] = std::move(value);
if(meta_range<internal::meta_prop_node *, internal::meta_prop_node> range{*ref}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [&instance](const auto *curr) { return curr->id == instance; }) == range.cend(), "Duplicate identifier");
node.next = *ref;
*ref = &node;
}
link_prop_if_required(node, property[0u]);
}
public:
@@ -139,7 +140,57 @@ private:
* @tparam Type Reflected type for which the factory was created.
*/
template<typename Type>
struct meta_factory<Type> {
class meta_factory<Type> {
void link_base_if_required(internal::meta_base_node &node) {
if(meta_range<internal::meta_base_node *, internal::meta_base_node> range{owner->base}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = owner->base;
owner->base = &node;
}
}
void link_conv_if_required(internal::meta_conv_node &node) {
if(meta_range<internal::meta_conv_node *, internal::meta_conv_node> range{owner->conv}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = owner->conv;
owner->conv = &node;
}
}
void link_ctor_if_required(internal::meta_ctor_node &node) {
if(meta_range<internal::meta_ctor_node *, internal::meta_ctor_node> range{owner->ctor}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = owner->ctor;
owner->ctor = &node;
}
}
void link_data_if_required(const id_type id, internal::meta_data_node &node) {
meta_range<internal::meta_data_node *, internal::meta_data_node> range{owner->data};
ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id, &node](const auto *curr) { return curr != &node && curr->id == id; }) == range.cend(), "Duplicate identifier");
node.id = id;
if(std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = owner->data;
owner->data = &node;
}
}
void link_func_if_required(const id_type id, internal::meta_func_node &node) {
for(auto *it = &owner->func; *it; it = &(*it)->next) {
if(*it == &node) {
*it = node.next;
break;
}
}
internal::meta_func_node **it = &owner->func;
for(; *it && (*it)->id != id; it = &(*it)->next);
for(; *it && (*it)->id == id && (*it)->arity < node.arity; it = &(*it)->next);
node.id = id;
node.next = *it;
*it = &node;
}
public:
/*! @brief Default constructor. */
meta_factory()
: owner{internal::meta_node<Type>::resolve()}
@@ -183,11 +234,7 @@ struct meta_factory<Type> {
}
};
if(meta_range<internal::meta_base_node *, internal::meta_base_node> range{owner->base}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = owner->base;
owner->base = &node;
}
link_base_if_required(node);
return meta_factory<Type>{};
}
@@ -215,11 +262,7 @@ struct meta_factory<Type> {
}
};
if(meta_range<internal::meta_conv_node *, internal::meta_conv_node> range{owner->conv}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = owner->conv;
owner->conv = &node;
}
link_conv_if_required(node);
return meta_factory<Type>{};
}
@@ -236,11 +279,7 @@ struct meta_factory<Type> {
}
};
if(meta_range<internal::meta_conv_node *, internal::meta_conv_node> range{owner->conv}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = owner->conv;
owner->conv = &node;
}
link_conv_if_required(node);
return meta_factory<Type>{};
}
@@ -265,11 +304,7 @@ struct meta_factory<Type> {
}
};
if(meta_range<internal::meta_conv_node *, internal::meta_conv_node> range{owner->conv}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = owner->conv;
owner->conv = &node;
}
link_conv_if_required(node);
return meta_factory<Type>{};
}
@@ -299,11 +334,7 @@ struct meta_factory<Type> {
&meta_construct<Type, Candidate, Policy>
};
if(meta_range<internal::meta_ctor_node *, internal::meta_ctor_node> range{owner->ctor}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = owner->ctor;
owner->ctor = &node;
}
link_ctor_if_required(node);
return meta_factory<Type, std::integral_constant<decltype(Candidate), Candidate>>{&node.prop};
}
@@ -329,11 +360,7 @@ struct meta_factory<Type> {
&meta_construct<Type, Args...>
};
if(meta_range<internal::meta_ctor_node *, internal::meta_ctor_node> range{owner->ctor}; std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = owner->ctor;
owner->ctor = &node;
}
link_ctor_if_required(node);
return meta_factory<Type, Type(Args...)>{&node.prop};
}
@@ -356,11 +383,7 @@ struct meta_factory<Type> {
template<auto Func>
auto dtor() ENTT_NOEXCEPT {
static_assert(std::is_invocable_v<decltype(Func), Type &>, "The function doesn't accept an object of the type provided");
owner->dtor = [](void *instance) {
Func(*static_cast<Type *>(instance));
};
owner->dtor = [](void *instance) { Func(*static_cast<Type *>(instance)); };
return meta_factory<Type>{};
}
@@ -396,15 +419,7 @@ struct meta_factory<Type> {
&meta_getter<Type, Data, Policy>
};
meta_range<internal::meta_data_node *, internal::meta_data_node> range{owner->data};
ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id](const auto *curr) { return curr != &node && curr->id == id; }) == range.cend(), "Duplicate identifier");
node.id = id;
if(std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = owner->data;
owner->data = &node;
}
link_data_if_required(id, node);
return meta_factory<Type, std::integral_constant<decltype(Data), Data>>{&node.prop};
}
}
@@ -445,15 +460,7 @@ struct meta_factory<Type> {
&meta_getter<Type, Getter, Policy>
};
meta_range<internal::meta_data_node *, internal::meta_data_node> range{owner->data};
ENTT_ASSERT(std::find_if(range.cbegin(), range.cend(), [id](const auto *curr) { return curr != &node && curr->id == id; }) == range.cend(), "Duplicate identifier");
node.id = id;
if(std::find(range.cbegin(), range.cend(), &node) == range.cend()) {
node.next = owner->data;
owner->data = &node;
}
link_data_if_required(id, node);
return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&node.prop};
}
@@ -487,21 +494,7 @@ struct meta_factory<Type> {
&meta_invoke<Type, Candidate, Policy>
};
for(auto *it = &owner->func; *it; it = &(*it)->next) {
if(*it == &node) {
*it = node.next;
break;
}
}
internal::meta_func_node **it = &owner->func;
for(; *it && (*it)->id != id; it = &(*it)->next);
for(; *it && (*it)->id == id && (*it)->arity < node.arity; it = &(*it)->next);
node.id = id;
node.next = *it;
*it = &node;
link_func_if_required(id, node);
return meta_factory<Type, std::integral_constant<decltype(Candidate), Candidate>>{&node.prop};
}