meta: hot/cold data to allow copies of meta nodes
This commit is contained in:
@@ -19,6 +19,27 @@
|
||||
|
||||
namespace entt {
|
||||
|
||||
/**
|
||||
* @cond TURN_OFF_DOXYGEN
|
||||
* Internal details not to be documented.
|
||||
*/
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename Type>
|
||||
void meta_details_setup(Type &value) {
|
||||
if(!value.details) {
|
||||
value.details = std::make_shared<typename decltype(value.details)::element_type>();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
/**
|
||||
* Internal details not to be documented.
|
||||
* @endcond
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Meta factory to be used for reflection purposes.
|
||||
*
|
||||
@@ -33,17 +54,17 @@ class meta_factory;
|
||||
/**
|
||||
* @brief Extended meta factory to be used for reflection purposes.
|
||||
* @tparam Type Reflected type for which the factory was created.
|
||||
* @tparam Prop Type of container to store properties.
|
||||
* @tparam Node Node for which to create properties, if any.
|
||||
*/
|
||||
template<typename Type, typename Prop>
|
||||
class meta_factory<Type, Prop>: public meta_factory<Type> {
|
||||
template<typename Type, typename Node>
|
||||
class meta_factory<Type, Node>: public meta_factory<Type> {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs an extended factory from a given node.
|
||||
* @param target The underlying container to store properties.
|
||||
* @param target The node for which to store properties, if any.
|
||||
*/
|
||||
meta_factory(Prop &target) noexcept
|
||||
: container{&target} {}
|
||||
meta_factory(Node &target) noexcept
|
||||
: node{&target} {}
|
||||
|
||||
/**
|
||||
* @brief Assigns a property to the last meta object created.
|
||||
@@ -57,7 +78,9 @@ public:
|
||||
*/
|
||||
template<typename... Value>
|
||||
meta_factory prop(id_type key, Value &&...value) {
|
||||
(*container)[key] = internal::meta_prop_node{
|
||||
internal::meta_details_setup(*node);
|
||||
|
||||
node->details->prop[key] = internal::meta_prop_node{
|
||||
&internal::resolve<std::decay_t<Value>>...,
|
||||
std::forward<Value>(value)...};
|
||||
|
||||
@@ -65,7 +88,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
Prop *container;
|
||||
Node *node;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -89,8 +112,9 @@ class meta_factory<Type> {
|
||||
+[](meta_handle instance, meta_any value) -> bool { return (meta_setter<Type, value_list_element_v<Index, Setter>>(*instance.operator->(), value.as_ref()) || ...); },
|
||||
&meta_getter<Type, Getter, Policy>};
|
||||
|
||||
auto it = owner->data.insert_or_assign(id, std::move(node)).first;
|
||||
return meta_factory<Type, decltype(internal::meta_data_node::prop)>{it->second.prop};
|
||||
internal::meta_details_setup(*owner);
|
||||
auto it = owner->details->data.insert_or_assign(id, std::move(node)).first;
|
||||
return meta_factory<Type, internal::meta_data_node>{it->second};
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -106,7 +130,7 @@ public:
|
||||
auto type(const id_type id) noexcept {
|
||||
ENTT_ASSERT(owner->id == id || !resolve(id), "Duplicate identifier");
|
||||
owner->id = id;
|
||||
return meta_factory<Type, decltype(internal::meta_type_node::prop)>{owner->prop};
|
||||
return meta_factory<Type, internal::meta_type_node>{*owner};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,8 +144,9 @@ public:
|
||||
template<typename Base>
|
||||
auto base() noexcept {
|
||||
static_assert(!std::is_same_v<Type, Base> && std::is_base_of_v<Base, Type>, "Invalid base type");
|
||||
internal::meta_details_setup(*owner);
|
||||
|
||||
owner->base[type_id<Base>().hash()] = internal::meta_base_node{
|
||||
owner->details->base[type_id<Base>().hash()] = internal::meta_base_node{
|
||||
&internal::resolve<Base>,
|
||||
+[](meta_any other) noexcept -> meta_any {
|
||||
if(auto *ptr = other.data(); ptr) {
|
||||
@@ -149,8 +174,9 @@ public:
|
||||
template<auto Candidate>
|
||||
auto conv() noexcept {
|
||||
using conv_type = std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<decltype(Candidate), Type &>>>;
|
||||
internal::meta_details_setup(*owner);
|
||||
|
||||
owner->conv[type_id<conv_type>().hash()] = internal::meta_conv_node{
|
||||
owner->details->conv[type_id<conv_type>().hash()] = internal::meta_conv_node{
|
||||
+[](const meta_any &instance) -> meta_any {
|
||||
return forward_as_meta(std::invoke(Candidate, *static_cast<const Type *>(instance.data())));
|
||||
}};
|
||||
@@ -170,8 +196,9 @@ public:
|
||||
template<typename To>
|
||||
auto conv() noexcept {
|
||||
using conv_type = std::remove_cv_t<std::remove_reference_t<To>>;
|
||||
internal::meta_details_setup(*owner);
|
||||
|
||||
owner->conv[type_id<conv_type>().hash()] = internal::meta_conv_node{
|
||||
owner->details->conv[type_id<conv_type>().hash()] = internal::meta_conv_node{
|
||||
+[](const meta_any &instance) -> meta_any {
|
||||
return forward_as_meta(static_cast<To>(*static_cast<const Type *>(instance.data())));
|
||||
}};
|
||||
@@ -197,8 +224,9 @@ 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_assert(std::is_same_v<std::remove_cv_t<std::remove_reference_t<typename descriptor::return_type>>, Type>, "The function doesn't return an object of the required type");
|
||||
internal::meta_details_setup(*owner);
|
||||
|
||||
owner->ctor[type_id<typename descriptor::args_type>().hash()] = internal::meta_ctor_node{
|
||||
owner->details->ctor[type_id<typename descriptor::args_type>().hash()] = internal::meta_ctor_node{
|
||||
descriptor::args_type::size,
|
||||
&meta_arg<typename descriptor::args_type>,
|
||||
&meta_construct<Type, Candidate, Policy>};
|
||||
@@ -219,8 +247,9 @@ public:
|
||||
template<typename... Args>
|
||||
auto ctor() noexcept {
|
||||
using descriptor = meta_function_helper_t<Type, Type (*)(Args...)>;
|
||||
internal::meta_details_setup(*owner);
|
||||
|
||||
owner->ctor[type_id<typename descriptor::args_type>().hash()] = internal::meta_ctor_node{
|
||||
owner->details->ctor[type_id<typename descriptor::args_type>().hash()] = internal::meta_ctor_node{
|
||||
descriptor::args_type::size,
|
||||
&meta_arg<typename descriptor::args_type>,
|
||||
&meta_construct<Type, Args...>};
|
||||
@@ -268,6 +297,8 @@ public:
|
||||
*/
|
||||
template<auto Data, typename Policy = as_is_t>
|
||||
auto data(const id_type id) noexcept {
|
||||
internal::meta_details_setup(*owner);
|
||||
|
||||
if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
|
||||
using data_type = std::remove_reference_t<std::invoke_result_t<decltype(Data), Type &>>;
|
||||
|
||||
@@ -280,8 +311,8 @@ public:
|
||||
&meta_setter<Type, Data>,
|
||||
&meta_getter<Type, Data, Policy>};
|
||||
|
||||
auto it = owner->data.insert_or_assign(id, std::move(node)).first;
|
||||
return meta_factory<Type, decltype(internal::meta_data_node::prop)>{it->second.prop};
|
||||
auto it = owner->details->data.insert_or_assign(id, std::move(node)).first;
|
||||
return meta_factory<Type, internal::meta_data_node>{it->second};
|
||||
} else {
|
||||
using data_type = std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>;
|
||||
|
||||
@@ -293,8 +324,8 @@ public:
|
||||
&meta_setter<Type, Data>,
|
||||
&meta_getter<Type, Data, Policy>};
|
||||
|
||||
auto it = owner->data.insert_or_assign(id, std::move(node)).first;
|
||||
return meta_factory<Type, decltype(internal::meta_data_node::prop)>{it->second.prop};
|
||||
auto it = owner->details->data.insert_or_assign(id, std::move(node)).first;
|
||||
return meta_factory<Type, internal::meta_data_node>{it->second};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +353,7 @@ public:
|
||||
auto data(const id_type id) noexcept {
|
||||
using data_type = std::invoke_result_t<decltype(Getter), Type &>;
|
||||
static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
|
||||
internal::meta_details_setup(*owner);
|
||||
|
||||
if constexpr(std::is_same_v<decltype(Setter), std::nullptr_t>) {
|
||||
internal::meta_data_node node{
|
||||
@@ -333,8 +365,8 @@ public:
|
||||
&meta_setter<Type, Setter>,
|
||||
&meta_getter<Type, Getter, Policy>};
|
||||
|
||||
auto it = owner->data.insert_or_assign(id, std::move(node)).first;
|
||||
return meta_factory<Type, decltype(internal::meta_data_node::prop)>{it->second.prop};
|
||||
auto it = owner->details->data.insert_or_assign(id, std::move(node)).first;
|
||||
return meta_factory<Type, internal::meta_data_node>{it->second};
|
||||
} else {
|
||||
using args_type = typename meta_function_helper_t<Type, decltype(Setter)>::args_type;
|
||||
|
||||
@@ -347,8 +379,8 @@ public:
|
||||
&meta_setter<Type, Setter>,
|
||||
&meta_getter<Type, Getter, Policy>};
|
||||
|
||||
auto it = owner->data.insert_or_assign(id, std::move(node)).first;
|
||||
return meta_factory<Type, decltype(internal::meta_data_node::prop)>{it->second.prop};
|
||||
auto it = owner->details->data.insert_or_assign(id, std::move(node)).first;
|
||||
return meta_factory<Type, internal::meta_data_node>{it->second};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,6 +423,7 @@ public:
|
||||
auto func(const id_type id) noexcept {
|
||||
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");
|
||||
internal::meta_details_setup(*owner);
|
||||
|
||||
internal::meta_func_node node{
|
||||
(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),
|
||||
@@ -399,22 +432,22 @@ public:
|
||||
&meta_arg<typename descriptor::args_type>,
|
||||
&meta_invoke<Type, Candidate, Policy>};
|
||||
|
||||
if(auto it = owner->func.find(id); it != owner->func.end()) {
|
||||
if(auto it = owner->details->func.find(id); it != owner->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);
|
||||
|
||||
return meta_factory<Type, decltype(internal::meta_func_node::prop)>{curr->prop};
|
||||
return meta_factory<Type, internal::meta_func_node>{*curr};
|
||||
}
|
||||
}
|
||||
|
||||
// locally overloaded function
|
||||
node.next = std::make_unique<internal::meta_func_node>(std::move(owner->func[id]));
|
||||
node.next = std::make_shared<internal::meta_func_node>(std::move(owner->details->func[id]));
|
||||
}
|
||||
|
||||
owner->func.insert_or_assign(id, std::move(node));
|
||||
return meta_factory<Type, decltype(internal::meta_func_node::prop)>{owner->func[id].prop};
|
||||
owner->details->func.insert_or_assign(id, std::move(node));
|
||||
return meta_factory<Type, internal::meta_func_node>{owner->details->func[id]};
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -436,7 +469,7 @@ template<typename Type>
|
||||
[[nodiscard]] auto meta() noexcept {
|
||||
auto *const node = internal::resolve<Type>();
|
||||
// extended meta factory to allow assigning properties to opaque meta types
|
||||
return meta_factory<Type, decltype(internal::meta_type_node::prop)>{node->prop};
|
||||
return meta_factory<Type, internal::meta_type_node>{*node};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -343,8 +343,8 @@ public:
|
||||
[[nodiscard]] const Type *try_cast() const {
|
||||
auto *self = any_cast<Type>(&storage);
|
||||
|
||||
if(!self && node) {
|
||||
for(auto it = node->base.cbegin(), last = node->base.cend(); it != last && !self; ++it) {
|
||||
if(!self && node && node->details) {
|
||||
for(auto it = node->details->base.cbegin(), last = node->details->base.cend(); it != last && !self; ++it) {
|
||||
const auto &as_const = it->second.cast(as_ref());
|
||||
self = as_const.template try_cast<Type>();
|
||||
}
|
||||
@@ -358,8 +358,8 @@ public:
|
||||
[[nodiscard]] Type *try_cast() {
|
||||
auto *self = any_cast<Type>(&storage);
|
||||
|
||||
if(!self && node) {
|
||||
for(auto it = node->base.cbegin(), last = node->base.cend(); it != last && !self; ++it) {
|
||||
if(!self && node && node->details) {
|
||||
for(auto it = node->details->base.cbegin(), last = node->details->base.cend(); it != last && !self; ++it) {
|
||||
self = it->second.cast(as_ref()).template try_cast<Type>();
|
||||
}
|
||||
}
|
||||
@@ -764,8 +764,12 @@ struct meta_data {
|
||||
* @brief Returns a range to visit registered meta properties.
|
||||
* @return An iterable range to visit registered meta properties.
|
||||
*/
|
||||
[[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_data_node::prop)::const_iterator> prop() const noexcept {
|
||||
return {node->prop.cbegin(), node->prop.cend()};
|
||||
[[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_data_node::cold_data_t::prop)::const_iterator> prop() const noexcept {
|
||||
if(node->details) {
|
||||
return {node->details->prop.cbegin(), node->details->prop.cend()};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -774,8 +778,10 @@ struct meta_data {
|
||||
* @return The registered meta property for the given key, if any.
|
||||
*/
|
||||
[[nodiscard]] meta_prop prop(const id_type key) const {
|
||||
if(auto it = node->prop.find(key); it != node->prop.cend()) {
|
||||
return &it->second;
|
||||
if(node->details) {
|
||||
if(auto it = node->details->prop.find(key); it != node->details->prop.cend()) {
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -876,8 +882,12 @@ struct meta_func {
|
||||
}
|
||||
|
||||
/*! @copydoc meta_data::prop */
|
||||
[[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_func_node::prop)::const_iterator> prop() const noexcept {
|
||||
return {node->prop.cbegin(), node->prop.cend()};
|
||||
[[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_func_node::cold_data_t::prop)::const_iterator> prop() const noexcept {
|
||||
if(node->details) {
|
||||
return {node->details->prop.cbegin(), node->details->prop.cend()};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -886,8 +896,10 @@ struct meta_func {
|
||||
* @return The registered meta property for the given key, if any.
|
||||
*/
|
||||
[[nodiscard]] meta_prop prop(const id_type key) const {
|
||||
if(auto it = node->prop.find(key); it != node->prop.cend()) {
|
||||
return &it->second;
|
||||
if(node->details) {
|
||||
if(auto it = node->details->prop.find(key); it != node->details->prop.cend()) {
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -935,7 +947,7 @@ class meta_type {
|
||||
if(const auto &info = other.info(); info == type.info()) {
|
||||
++direct;
|
||||
} else {
|
||||
ext += type.node->base.contains(info.hash()) || type.node->conv.contains(info.hash())
|
||||
ext += (type.node->details && (type.node->details->base.contains(info.hash()) || type.node->details->conv.contains(info.hash())))
|
||||
|| (type.node->conversion_helper && other.node->conversion_helper);
|
||||
}
|
||||
}
|
||||
@@ -1131,16 +1143,24 @@ public:
|
||||
* @brief Returns a range to visit registered top-level base meta types.
|
||||
* @return An iterable range to visit registered top-level base meta types.
|
||||
*/
|
||||
[[nodiscard]] meta_range<meta_type, typename decltype(internal::meta_type_node::base)::const_iterator> base() const noexcept {
|
||||
return {node->base.cbegin(), node->base.cend()};
|
||||
[[nodiscard]] meta_range<meta_type, typename decltype(internal::meta_type_node::cold_data_t::base)::const_iterator> base() const noexcept {
|
||||
if(node->details) {
|
||||
return {node->details->base.cbegin(), node->details->base.cend()};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a range to visit registered top-level meta data.
|
||||
* @return An iterable range to visit registered top-level meta data.
|
||||
*/
|
||||
[[nodiscard]] meta_range<meta_data, typename decltype(internal::meta_type_node::data)::const_iterator> data() const noexcept {
|
||||
return {node->data.cbegin(), node->data.cend()};
|
||||
[[nodiscard]] meta_range<meta_data, typename decltype(internal::meta_type_node::cold_data_t::data)::const_iterator> data() const noexcept {
|
||||
if(node->details) {
|
||||
return {node->details->data.cbegin(), node->details->data.cend()};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1152,8 +1172,10 @@ public:
|
||||
* @return The registered meta data for the given identifier, if any.
|
||||
*/
|
||||
[[nodiscard]] meta_data data(const id_type id) const {
|
||||
if(auto it = node->data.find(id); it != node->data.cend()) {
|
||||
return &it->second;
|
||||
if(node->details) {
|
||||
if(auto it = node->details->data.find(id); it != node->details->data.cend()) {
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
|
||||
for(auto &&curr: base()) {
|
||||
@@ -1169,8 +1191,12 @@ public:
|
||||
* @brief Returns a range to visit registered top-level functions.
|
||||
* @return An iterable range to visit registered top-level functions.
|
||||
*/
|
||||
[[nodiscard]] meta_range<meta_func, typename decltype(internal::meta_type_node::func)::const_iterator> func() const noexcept {
|
||||
return {node->func.cbegin(), node->func.cend()};
|
||||
[[nodiscard]] meta_range<meta_func, typename decltype(internal::meta_type_node::cold_data_t::func)::const_iterator> func() const noexcept {
|
||||
if(node->details) {
|
||||
return {node->details->func.cbegin(), node->details->func.cend()};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1184,8 +1210,10 @@ public:
|
||||
* @return The registered meta function for the given identifier, if any.
|
||||
*/
|
||||
[[nodiscard]] meta_func func(const id_type id) const {
|
||||
if(auto it = node->func.find(id); it != node->func.cend()) {
|
||||
return &it->second;
|
||||
if(node->details) {
|
||||
if(auto it = node->details->func.find(id); it != node->details->func.cend()) {
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
|
||||
for(auto &&curr: base()) {
|
||||
@@ -1209,15 +1237,21 @@ public:
|
||||
* @return A wrapper containing the new instance, if any.
|
||||
*/
|
||||
[[nodiscard]] meta_any construct(meta_any *const args, const size_type sz) const {
|
||||
const auto *candidate = lookup(args, sz, [first = node->ctor.cbegin(), last = node->ctor.cend()]() mutable {
|
||||
return first == last ? nullptr : &(first++)->second;
|
||||
});
|
||||
if(node->details) {
|
||||
const auto *candidate = lookup(args, sz, [first = node->details->ctor.cbegin(), last = node->details->ctor.cend()]() mutable {
|
||||
return first == last ? nullptr : &(first++)->second;
|
||||
});
|
||||
|
||||
if(candidate) {
|
||||
return candidate->invoke(args);
|
||||
if(candidate) {
|
||||
return candidate->invoke(args);
|
||||
}
|
||||
}
|
||||
|
||||
return (sz == 0u && node->default_constructor) ? node->default_constructor() : meta_any{};
|
||||
if(sz == 0u && node->default_constructor) {
|
||||
return node->default_constructor();
|
||||
}
|
||||
|
||||
return meta_any{};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1264,13 +1298,15 @@ 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(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(node->details) {
|
||||
if(auto it = node->details->func.find(id); it != node->details->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);
|
||||
if(candidate) {
|
||||
return candidate->invoke(std::move(instance), args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1339,8 +1375,12 @@ public:
|
||||
* @brief Returns a range to visit registered top-level meta properties.
|
||||
* @return An iterable range to visit registered top-level meta properties.
|
||||
*/
|
||||
[[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_type_node::prop)::const_iterator> prop() const noexcept {
|
||||
return {node->prop.cbegin(), node->prop.cend()};
|
||||
[[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_type_node::cold_data_t::prop)::const_iterator> prop() const noexcept {
|
||||
if(node->details) {
|
||||
return {node->details->prop.cbegin(), node->details->prop.cend()};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1352,8 +1392,10 @@ public:
|
||||
* @return The registered meta property for the given key, if any.
|
||||
*/
|
||||
[[nodiscard]] meta_prop prop(const id_type key) const {
|
||||
if(auto it = node->prop.find(key); it != node->prop.cend()) {
|
||||
return &it->second;
|
||||
if(node->details) {
|
||||
if(auto it = node->details->prop.find(key); it != node->details->prop.cend()) {
|
||||
return &it->second;
|
||||
}
|
||||
}
|
||||
|
||||
for(auto &&curr: base()) {
|
||||
@@ -1427,8 +1469,10 @@ bool meta_any::set(const id_type id, Type &&value) {
|
||||
if(const auto &info = type.info(); node && *node->info == info) {
|
||||
return as_ref();
|
||||
} else if(node) {
|
||||
if(auto it = node->conv.find(info.hash()); it != node->conv.cend()) {
|
||||
return it->second.conv(*this);
|
||||
if(node->details) {
|
||||
if(auto it = node->details->conv.find(info.hash()); it != node->details->conv.cend()) {
|
||||
return it->second.conv(*this);
|
||||
}
|
||||
}
|
||||
|
||||
if(node->conversion_helper && (type.is_arithmetic() || type.is_enum())) {
|
||||
@@ -1440,11 +1484,13 @@ bool meta_any::set(const id_type id, Type &&value) {
|
||||
return other;
|
||||
}
|
||||
|
||||
for(auto &&curr: node->base) {
|
||||
const auto &as_const = curr.second.cast(as_ref());
|
||||
if(node->details) {
|
||||
for(auto &&curr: node->details->base) {
|
||||
const auto &as_const = curr.second.cast(as_ref());
|
||||
|
||||
if(auto other = as_const.allow_cast(type); other) {
|
||||
return other;
|
||||
if(auto other = as_const.allow_cast(type); other) {
|
||||
return other;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,25 +76,33 @@ struct meta_dtor_node {
|
||||
struct meta_data_node {
|
||||
using size_type = std::size_t;
|
||||
|
||||
struct cold_data_t {
|
||||
dense_map<id_type, meta_prop_node, identity> prop;
|
||||
};
|
||||
|
||||
meta_traits traits{meta_traits::is_none};
|
||||
size_type arity{0u};
|
||||
meta_type_node *(*type)() noexcept {nullptr};
|
||||
meta_type (*arg)(const size_type) noexcept {nullptr};
|
||||
bool (*set)(meta_handle, meta_any){nullptr};
|
||||
meta_any (*get)(meta_handle){nullptr};
|
||||
dense_map<id_type, meta_prop_node, identity> prop{};
|
||||
std::shared_ptr<cold_data_t> details{};
|
||||
};
|
||||
|
||||
struct meta_func_node {
|
||||
using size_type = std::size_t;
|
||||
|
||||
struct cold_data_t {
|
||||
dense_map<id_type, meta_prop_node, identity> prop;
|
||||
};
|
||||
|
||||
meta_traits traits{meta_traits::is_none};
|
||||
size_type arity{0u};
|
||||
meta_type_node *(*ret)() noexcept {nullptr};
|
||||
meta_type (*arg)(const size_type) noexcept {nullptr};
|
||||
meta_any (*invoke)(meta_handle, meta_any *const){nullptr};
|
||||
dense_map<id_type, meta_prop_node, identity> prop{};
|
||||
std::unique_ptr<meta_func_node> next{};
|
||||
std::shared_ptr<meta_func_node> next{};
|
||||
std::shared_ptr<cold_data_t> details{};
|
||||
};
|
||||
|
||||
struct meta_template_node {
|
||||
@@ -108,6 +116,15 @@ struct meta_template_node {
|
||||
struct meta_type_node {
|
||||
using size_type = std::size_t;
|
||||
|
||||
struct cold_data_t {
|
||||
dense_map<id_type, meta_prop_node, identity> prop{};
|
||||
dense_map<id_type, meta_ctor_node, identity> ctor{};
|
||||
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{};
|
||||
dense_map<id_type, meta_func_node, identity> func{};
|
||||
};
|
||||
|
||||
const type_info *info{nullptr};
|
||||
id_type id{};
|
||||
meta_traits traits{meta_traits::is_none};
|
||||
@@ -117,13 +134,8 @@ struct meta_type_node {
|
||||
double (*conversion_helper)(void *, const void *){nullptr};
|
||||
meta_any (*from_void)(void *, const void *){nullptr};
|
||||
meta_template_node templ{};
|
||||
dense_map<id_type, meta_prop_node, identity> prop{};
|
||||
dense_map<id_type, meta_ctor_node, identity> ctor{};
|
||||
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{};
|
||||
dense_map<id_type, meta_func_node, identity> func{};
|
||||
meta_dtor_node dtor{};
|
||||
std::shared_ptr<cold_data_t> details{};
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
|
||||
@@ -183,6 +183,7 @@ TEST_F(MetaBase, ReRegistration) {
|
||||
|
||||
auto *node = entt::internal::resolve<derived_t>();
|
||||
|
||||
ASSERT_FALSE(node->base.empty());
|
||||
ASSERT_EQ(node->base.size(), 2u);
|
||||
ASSERT_TRUE(node->details);
|
||||
ASSERT_FALSE(node->details->base.empty());
|
||||
ASSERT_EQ(node->details->base.size(), 2u);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ TEST_F(MetaConv, ReRegistration) {
|
||||
|
||||
auto *node = entt::internal::resolve<clazz_t>();
|
||||
|
||||
ASSERT_FALSE(node->conv.empty());
|
||||
ASSERT_EQ(node->conv.size(), 3u);
|
||||
ASSERT_TRUE(node->details);
|
||||
ASSERT_FALSE(node->details->conv.empty());
|
||||
ASSERT_EQ(node->details->conv.size(), 3u);
|
||||
}
|
||||
|
||||
@@ -207,7 +207,8 @@ TEST_F(MetaCtor, ReRegistration) {
|
||||
|
||||
auto *node = entt::internal::resolve<double>();
|
||||
|
||||
ASSERT_FALSE(node->ctor.empty());
|
||||
ASSERT_TRUE(node->details);
|
||||
ASSERT_FALSE(node->details->ctor.empty());
|
||||
// implicitly generated default constructor is not cleared
|
||||
ASSERT_NE(node->default_constructor, nullptr);
|
||||
}
|
||||
|
||||
@@ -646,13 +646,15 @@ TEST_F(MetaData, ReRegistration) {
|
||||
auto *node = entt::internal::resolve<base_t>();
|
||||
auto type = entt::resolve<base_t>();
|
||||
|
||||
ASSERT_FALSE(node->data.empty());
|
||||
ASSERT_EQ(node->data.size(), 1u);
|
||||
ASSERT_TRUE(node->details);
|
||||
ASSERT_FALSE(node->details->data.empty());
|
||||
ASSERT_EQ(node->details->data.size(), 1u);
|
||||
ASSERT_TRUE(type.data("value"_hs));
|
||||
|
||||
entt::meta<base_t>().data<&base_t::value>("field"_hs);
|
||||
|
||||
ASSERT_EQ(node->data.size(), 2u);
|
||||
ASSERT_TRUE(node->details);
|
||||
ASSERT_EQ(node->details->data.size(), 2u);
|
||||
ASSERT_TRUE(type.data("value"_hs));
|
||||
ASSERT_TRUE(type.data("field"_hs));
|
||||
}
|
||||
|
||||
@@ -89,8 +89,9 @@ TEST_F(MetaProp, ReRegistration) {
|
||||
auto *node = entt::internal::resolve<base_1_t>();
|
||||
auto type = entt::resolve<base_1_t>();
|
||||
|
||||
ASSERT_FALSE(node->prop.empty());
|
||||
ASSERT_EQ(node->prop.size(), 1u);
|
||||
ASSERT_TRUE(node->details);
|
||||
ASSERT_FALSE(node->details->prop.empty());
|
||||
ASSERT_EQ(node->details->prop.size(), 1u);
|
||||
|
||||
ASSERT_TRUE(type.prop("int"_hs));
|
||||
ASSERT_EQ(type.prop("int"_hs).value().cast<int>(), 42);
|
||||
@@ -98,8 +99,9 @@ TEST_F(MetaProp, ReRegistration) {
|
||||
entt::meta<base_1_t>().prop("int"_hs, 0);
|
||||
entt::meta<base_1_t>().prop("double"_hs, 3.);
|
||||
|
||||
ASSERT_FALSE(node->prop.empty());
|
||||
ASSERT_EQ(node->prop.size(), 2u);
|
||||
ASSERT_TRUE(node->details);
|
||||
ASSERT_FALSE(node->details->prop.empty());
|
||||
ASSERT_EQ(node->details->prop.size(), 2u);
|
||||
|
||||
ASSERT_TRUE(type.prop("int"_hs));
|
||||
ASSERT_TRUE(type.prop("double"_hs));
|
||||
|
||||
Reference in New Issue
Block a user