meta: added underlying context
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include "../config/config.h"
|
||||
#include "../core/utility.hpp"
|
||||
#include "policy.hpp"
|
||||
#include "meta.hpp"
|
||||
|
||||
@@ -304,10 +303,10 @@ public:
|
||||
|
||||
node->identifier = identifier;
|
||||
node->prop = properties<Type>(std::forward<Property>(property)...);
|
||||
ENTT_ASSERT(!duplicate(identifier, internal::meta_info<>::type));
|
||||
ENTT_ASSERT(!duplicate(node, internal::meta_info<>::type));
|
||||
node->next = internal::meta_info<>::type;
|
||||
internal::meta_info<>::type = node;
|
||||
ENTT_ASSERT(!duplicate(identifier, *internal::meta_info<>::ctx));
|
||||
ENTT_ASSERT(!duplicate(node, *internal::meta_info<>::ctx));
|
||||
node->next = *internal::meta_info<>::ctx;
|
||||
*internal::meta_info<>::ctx = node;
|
||||
|
||||
return *this;
|
||||
}
|
||||
@@ -710,38 +709,7 @@ public:
|
||||
* removed.
|
||||
*/
|
||||
void unregister() ENTT_NOEXCEPT {
|
||||
auto * const node = internal::meta_info<Type>::resolve();
|
||||
auto **curr = &internal::meta_info<>::type;
|
||||
|
||||
while(*curr && *curr != node) {
|
||||
curr = &(*curr)->next;
|
||||
}
|
||||
|
||||
if(*curr) {
|
||||
*curr = (*curr)->next;
|
||||
}
|
||||
|
||||
const auto unregister_all = y_combinator{
|
||||
[](auto &&self, auto **node, auto... member) {
|
||||
while(*node) {
|
||||
auto *curr = *node;
|
||||
(self(&(curr->*member)), ...);
|
||||
*node = curr->next;
|
||||
curr->next = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
unregister_all(&node->prop);
|
||||
unregister_all(&node->base);
|
||||
unregister_all(&node->conv);
|
||||
unregister_all(&node->ctor, &internal::meta_ctor_node::prop);
|
||||
unregister_all(&node->data, &internal::meta_data_node::prop);
|
||||
unregister_all(&node->func, &internal::meta_func_node::prop);
|
||||
|
||||
node->dtor = nullptr;
|
||||
node->identifier = {};
|
||||
node->next = nullptr;
|
||||
internal::meta_info<Type>::reset();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -819,7 +787,7 @@ inline meta_type resolve() ENTT_NOEXCEPT {
|
||||
inline meta_type resolve(const ENTT_ID_TYPE identifier) ENTT_NOEXCEPT {
|
||||
return internal::find_if([identifier](auto *node) {
|
||||
return node->identifier == identifier;
|
||||
}, internal::meta_info<>::type);
|
||||
}, *internal::meta_info<>::ctx);
|
||||
}
|
||||
|
||||
|
||||
@@ -831,7 +799,7 @@ inline meta_type resolve(const ENTT_ID_TYPE identifier) ENTT_NOEXCEPT {
|
||||
template<typename Op>
|
||||
inline std::enable_if_t<std::is_invocable_v<Op, meta_type>, void>
|
||||
resolve(Op op) ENTT_NOEXCEPT {
|
||||
internal::iterate<meta_type>(std::move(op), internal::meta_info<>::type);
|
||||
internal::iterate<meta_type>(std::move(op), *internal::meta_info<>::ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <type_traits>
|
||||
#include "../config/config.h"
|
||||
#include "../core/type_traits.hpp"
|
||||
#include "../core/utility.hpp"
|
||||
|
||||
|
||||
namespace entt {
|
||||
@@ -17,7 +18,7 @@ namespace entt {
|
||||
|
||||
class meta_any;
|
||||
class meta_handle;
|
||||
struct meta_type;
|
||||
class meta_type;
|
||||
|
||||
|
||||
/**
|
||||
@@ -128,60 +129,6 @@ struct meta_type_node {
|
||||
};
|
||||
|
||||
|
||||
template<typename...>
|
||||
struct meta_node;
|
||||
|
||||
|
||||
template<>
|
||||
struct meta_node<> {
|
||||
inline static meta_type_node *type = nullptr;
|
||||
};
|
||||
|
||||
|
||||
template<typename Type>
|
||||
static bool compare(const void *lhs, const void *rhs) {
|
||||
if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
|
||||
return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
|
||||
} else {
|
||||
return lhs == rhs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename Type>
|
||||
struct meta_node<Type> {
|
||||
static meta_type_node * resolve() ENTT_NOEXCEPT {
|
||||
static meta_type_node node{
|
||||
{},
|
||||
nullptr,
|
||||
nullptr,
|
||||
std::is_void_v<Type>,
|
||||
std::is_integral_v<Type>,
|
||||
std::is_floating_point_v<Type>,
|
||||
std::is_array_v<Type>,
|
||||
std::is_enum_v<Type>,
|
||||
std::is_union_v<Type>,
|
||||
std::is_class_v<Type>,
|
||||
std::is_pointer_v<Type>,
|
||||
std::is_pointer_v<Type> && std::is_function_v<std::remove_pointer_t<Type>>,
|
||||
std::is_member_object_pointer_v<Type>,
|
||||
std::is_member_function_pointer_v<Type>,
|
||||
std::extent_v<Type>,
|
||||
&compare<Type>, // workaround for an issue with VS2017
|
||||
[]() ENTT_NOEXCEPT -> meta_type_node * {
|
||||
return meta_node<std::remove_const_t<std::remove_pointer_t<Type>>>::resolve();
|
||||
}
|
||||
};
|
||||
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename... Type>
|
||||
struct meta_info: meta_node<std::remove_cv_t<std::remove_reference_t<Type>>...> {};
|
||||
|
||||
|
||||
template<typename Type, typename Op, typename Node>
|
||||
void iterate(Op op, const Node *curr) ENTT_NOEXCEPT {
|
||||
while(curr) {
|
||||
@@ -235,42 +182,110 @@ auto find_if(Op op, const meta_type_node *node) ENTT_NOEXCEPT
|
||||
|
||||
|
||||
template<typename Type>
|
||||
const Type * try_cast(const meta_type_node *node, void *instance) ENTT_NOEXCEPT {
|
||||
const auto * const type = meta_info<Type>::resolve();
|
||||
void *ret = nullptr;
|
||||
|
||||
if(node == type) {
|
||||
ret = instance;
|
||||
static bool compare(const void *lhs, const void *rhs) {
|
||||
if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
|
||||
return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
|
||||
} else {
|
||||
const auto *base = find_if<&meta_type_node::base>([type](auto *candidate) {
|
||||
return candidate->type() == type;
|
||||
}, node);
|
||||
return lhs == rhs;
|
||||
}
|
||||
}
|
||||
|
||||
ret = base ? base->cast(instance) : nullptr;
|
||||
|
||||
template<typename...>
|
||||
struct meta_node;
|
||||
|
||||
|
||||
template<>
|
||||
struct meta_node<> {
|
||||
inline static meta_type_node *local = nullptr;
|
||||
inline static meta_type_node **ctx = &local;
|
||||
};
|
||||
|
||||
|
||||
template<typename Type>
|
||||
struct meta_node<Type> {
|
||||
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>);
|
||||
inline static meta_type_node *type = nullptr;
|
||||
|
||||
static void reset() ENTT_NOEXCEPT {
|
||||
auto * const node = type ? type : resolve();
|
||||
auto **curr = meta_node<>::ctx;
|
||||
|
||||
while(*curr && *curr != node) {
|
||||
curr = &(*curr)->next;
|
||||
}
|
||||
|
||||
if(*curr) {
|
||||
*curr = (*curr)->next;
|
||||
}
|
||||
|
||||
const auto unregister_all = y_combinator{
|
||||
[](auto &&self, auto **node, auto... member) {
|
||||
while(*node) {
|
||||
auto *curr = *node;
|
||||
(self(&(curr->*member)), ...);
|
||||
*node = curr->next;
|
||||
curr->next = nullptr;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
unregister_all(&node->prop);
|
||||
unregister_all(&node->base);
|
||||
unregister_all(&node->conv);
|
||||
unregister_all(&node->ctor, &internal::meta_ctor_node::prop);
|
||||
unregister_all(&node->data, &internal::meta_data_node::prop);
|
||||
unregister_all(&node->func, &internal::meta_func_node::prop);
|
||||
|
||||
node->identifier = {};
|
||||
node->dtor = nullptr;
|
||||
node->next = nullptr;
|
||||
|
||||
type = nullptr;
|
||||
}
|
||||
|
||||
return static_cast<const Type *>(ret);
|
||||
}
|
||||
static meta_type_node * resolve() ENTT_NOEXCEPT {
|
||||
static meta_type_node node{
|
||||
{},
|
||||
nullptr,
|
||||
nullptr,
|
||||
std::is_void_v<Type>,
|
||||
std::is_integral_v<Type>,
|
||||
std::is_floating_point_v<Type>,
|
||||
std::is_array_v<Type>,
|
||||
std::is_enum_v<Type>,
|
||||
std::is_union_v<Type>,
|
||||
std::is_class_v<Type>,
|
||||
std::is_pointer_v<Type>,
|
||||
std::is_pointer_v<Type> && std::is_function_v<std::remove_pointer_t<Type>>,
|
||||
std::is_member_object_pointer_v<Type>,
|
||||
std::is_member_function_pointer_v<Type>,
|
||||
std::extent_v<Type>,
|
||||
&compare<Type>, // workaround for an issue with VS2017
|
||||
[]() ENTT_NOEXCEPT -> meta_type_node * {
|
||||
return meta_node<std::remove_const_t<std::remove_pointer_t<Type>>>::resolve();
|
||||
}
|
||||
};
|
||||
|
||||
if(!type) {
|
||||
if constexpr(is_named_type_v<Type>) {
|
||||
iterate<meta_type_node>([](const auto *node) {
|
||||
if(node->identifer == named_type_traits<Type>::value) {
|
||||
type = node;
|
||||
}
|
||||
}, *meta_node<>::ctx);
|
||||
} else {
|
||||
type = &node;
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<auto Member>
|
||||
inline bool can_cast_or_convert(const meta_type_node *from, const meta_type_node *to) ENTT_NOEXCEPT {
|
||||
return (from == to) || find_if<Member>([to](auto *node) {
|
||||
return node->type() == to;
|
||||
}, from);
|
||||
}
|
||||
|
||||
|
||||
template<typename... Args, std::size_t... Indexes>
|
||||
inline auto ctor(std::index_sequence<Indexes...>, const meta_type_node *node) ENTT_NOEXCEPT {
|
||||
return internal::find_if([](auto *candidate) {
|
||||
return candidate->size == sizeof...(Args) &&
|
||||
(([](auto *from, auto *to) {
|
||||
return internal::can_cast_or_convert<&internal::meta_type_node::base>(from, to)
|
||||
|| internal::can_cast_or_convert<&internal::meta_type_node::conv>(from, to);
|
||||
}(internal::meta_info<Args>::resolve(), candidate->arg(Indexes))) && ...);
|
||||
}, node->ctor);
|
||||
}
|
||||
template<typename... Type>
|
||||
struct meta_info: meta_node<std::remove_cv_t<std::remove_reference_t<Type>>...> {};
|
||||
|
||||
|
||||
}
|
||||
@@ -511,7 +526,20 @@ public:
|
||||
*/
|
||||
template<typename Type>
|
||||
const Type * try_cast() const ENTT_NOEXCEPT {
|
||||
return internal::try_cast<Type>(node, instance);
|
||||
const auto * const type = internal::meta_info<Type>::resolve();
|
||||
void *ret = nullptr;
|
||||
|
||||
if(node == type) {
|
||||
ret = instance;
|
||||
} else {
|
||||
const auto *base = internal::find_if<&internal::meta_type_node::base>([type](auto *candidate) {
|
||||
return candidate->type() == type;
|
||||
}, node);
|
||||
|
||||
ret = base ? base->cast(instance) : nullptr;
|
||||
}
|
||||
|
||||
return static_cast<const Type *>(ret);
|
||||
}
|
||||
|
||||
/*! @copydoc try_cast */
|
||||
@@ -599,7 +627,7 @@ public:
|
||||
* @param args Parameters to use to construct the instance.
|
||||
*/
|
||||
template<typename Type, typename... Args>
|
||||
void emplace(Args&& ... args) {
|
||||
void emplace(Args &&... args) {
|
||||
*this = meta_any{std::in_place_type_t<Type>{}, std::forward<Args>(args)...};
|
||||
}
|
||||
|
||||
@@ -1330,7 +1358,18 @@ inline bool operator!=(const meta_func &lhs, const meta_func &rhs) ENTT_NOEXCEPT
|
||||
|
||||
|
||||
/*! @brief Opaque container for meta types. */
|
||||
struct meta_type {
|
||||
class meta_type {
|
||||
template<typename... Args, std::size_t... Indexes>
|
||||
auto ctor(std::index_sequence<Indexes...>, const internal::meta_type_node *node) const ENTT_NOEXCEPT {
|
||||
return internal::find_if([](auto *candidate) {
|
||||
return candidate->size == sizeof...(Args) && ([](auto *from, auto *to) {
|
||||
return (from == to) || internal::find_if<&internal::meta_type_node::base>([to](auto *node) { return node->type() == to; }, from)
|
||||
|| internal::find_if<&internal::meta_type_node::conv>([to](auto *node) { return node->type() == to; }, from);
|
||||
}(internal::meta_info<Args>::resolve(), candidate->arg(Indexes)) && ...);
|
||||
}, node->ctor);
|
||||
}
|
||||
|
||||
public:
|
||||
/*! @brief Unsigned integer type. */
|
||||
using size_type = typename internal::meta_type_node::size_type;
|
||||
|
||||
@@ -1540,7 +1579,7 @@ struct meta_type {
|
||||
*/
|
||||
template<typename... Args>
|
||||
meta_ctor ctor() const ENTT_NOEXCEPT {
|
||||
return internal::ctor<Args...>(std::make_index_sequence<sizeof...(Args)>{}, node);
|
||||
return ctor<Args...>(std::make_index_sequence<sizeof...(Args)>{}, node);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1969,20 +1969,27 @@ TEST_F(Meta, Variables) {
|
||||
}
|
||||
|
||||
TEST_F(Meta, Unregister) {
|
||||
entt::unregister<double>();
|
||||
ASSERT_NE(*entt::internal::meta_info<>::ctx, nullptr);
|
||||
ASSERT_NE(entt::internal::meta_info<>::local, nullptr);
|
||||
|
||||
entt::unregister<char>();
|
||||
entt::unregister<properties>();
|
||||
entt::unregister<unsigned int>();
|
||||
entt::unregister<base_type>();
|
||||
entt::unregister<derived_type>();
|
||||
entt::unregister<empty_type>();
|
||||
entt::unregister<concrete_type>();
|
||||
entt::unregister<setter_getter_type>();
|
||||
entt::unregister<fat_type>();
|
||||
entt::unregister<data_type>();
|
||||
entt::unregister<func_type>();
|
||||
entt::unregister<setter_getter_type>();
|
||||
entt::unregister<array_type>();
|
||||
entt::unregister<double>();
|
||||
entt::unregister<properties>();
|
||||
entt::unregister<base_type>();
|
||||
entt::unregister<derived_type>();
|
||||
entt::unregister<empty_type>();
|
||||
entt::unregister<an_abstract_type>();
|
||||
entt::unregister<another_abstract_type>();
|
||||
entt::unregister<concrete_type>();
|
||||
entt::unregister<unsigned int>();
|
||||
|
||||
ASSERT_EQ(*entt::internal::meta_info<>::ctx, nullptr);
|
||||
ASSERT_EQ(entt::internal::meta_info<>::local, nullptr);
|
||||
|
||||
ASSERT_FALSE(entt::resolve("char"_hs));
|
||||
ASSERT_FALSE(entt::resolve("base"_hs));
|
||||
|
||||
Reference in New Issue
Block a user