meta: reset-all functionality (see #358)
This commit is contained in:
@@ -583,3 +583,14 @@ entt::meta<my_type>().reset();
|
||||
```
|
||||
|
||||
The type can be re-registered later with a completely different name and form.
|
||||
|
||||
To unregister all the types at once instead, a generic meta factory is the way
|
||||
to go:
|
||||
|
||||
```cpp
|
||||
entt::meta().reset();
|
||||
```
|
||||
|
||||
This function may touch more meta types than those explicitly created by the
|
||||
user. In fact, all locally created meta types are visited and reset, including
|
||||
those implicitly generated by the meta system under the hood.
|
||||
|
||||
@@ -241,17 +241,45 @@ class extended_meta_factory;
|
||||
|
||||
|
||||
/**
|
||||
* @brief A meta factory to be used for reflection purposes.
|
||||
*
|
||||
* A meta factory is an utility class used to reflect types, data and functions
|
||||
* of all sorts. This class ensures that the underlying web of types is built
|
||||
* correctly and performs some checks in debug mode to ensure that there are no
|
||||
* subtle errors at runtime.
|
||||
* @brief Meta factory to be used for reflection purposes.
|
||||
*
|
||||
* The meta factory is an utility class used to reflect types, data members and
|
||||
* functions of all sorts. This class ensures that the underlying web of types
|
||||
* is built correctly and performs some checks in debug mode to ensure that
|
||||
* there are no subtle errors at runtime.
|
||||
*/
|
||||
template<typename...>
|
||||
class meta_factory;
|
||||
|
||||
|
||||
/*! @brief Generic meta factory to be used for reflection purposes. */
|
||||
template<>
|
||||
class meta_factory<> {
|
||||
public:
|
||||
/**
|
||||
* @brief Resets all meta types and all their parts.
|
||||
*
|
||||
* This function resets all meta type and their data members, member
|
||||
* functions and properties, as well as their constructors, destructors,
|
||||
* base classes and conversion functions if any.
|
||||
*/
|
||||
void reset() ENTT_NOEXCEPT {
|
||||
auto *it = internal::meta_info<>::context;
|
||||
|
||||
while(it) {
|
||||
internal::meta_info<>::reset(it);
|
||||
it = it->context;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Basic meta factory to be used for reflection purposes.
|
||||
* @tparam Type Reflected type for which the factory was created.
|
||||
*/
|
||||
template<typename Type>
|
||||
class meta_factory {
|
||||
class meta_factory<Type> {
|
||||
template<typename Node>
|
||||
bool duplicate(const Node *candidate, const Node *node) ENTT_NOEXCEPT {
|
||||
return node && (node == candidate || duplicate(candidate, node->next));
|
||||
@@ -269,6 +297,8 @@ class meta_factory {
|
||||
ENTT_ASSERT(!duplicate(node, *internal::meta_info<>::global));
|
||||
node->identifier = identifier;
|
||||
node->next = *internal::meta_info<>::global;
|
||||
if(node->next) { node->next->hook = &node->next; }
|
||||
node->hook = internal::meta_info<>::global;
|
||||
*internal::meta_info<>::global = node;
|
||||
|
||||
return extended_meta_factory<Type>{&node->prop};
|
||||
@@ -281,7 +311,7 @@ public:
|
||||
* This function is intended only for unnamed types.
|
||||
*
|
||||
* @param identifier Unique identifier.
|
||||
* @return An extended meta factory for the parent type.
|
||||
* @return An extended meta factory for the given type.
|
||||
*/
|
||||
auto type(const ENTT_ID_TYPE identifier) ENTT_NOEXCEPT {
|
||||
static_assert(!is_named_type_v<Type>);
|
||||
@@ -293,7 +323,7 @@ public:
|
||||
*
|
||||
* This function is intended only for named types
|
||||
*
|
||||
* @return An extended meta factory for the parent type.
|
||||
* @return An extended meta factory for the given type.
|
||||
*/
|
||||
auto type() ENTT_NOEXCEPT {
|
||||
static_assert(is_named_type_v<Type>);
|
||||
@@ -678,7 +708,7 @@ public:
|
||||
* Base classes aren't reset but the link between the two types is removed.
|
||||
*/
|
||||
void reset() ENTT_NOEXCEPT {
|
||||
internal::meta_info<Type>::reset();
|
||||
internal::meta_info<>::reset(internal::meta_info<Type>::resolve());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -806,14 +836,15 @@ private:
|
||||
* This is the point from which everything starts.<br/>
|
||||
* By invoking this function with a type that is not yet reflected, a meta type
|
||||
* is created to which it will be possible to attach meta objects through a
|
||||
* dedicated factory.
|
||||
* dedicated factory. If no type is provided, a generic meta factory is returned
|
||||
* instead.
|
||||
*
|
||||
* @tparam Type Type to reflect.
|
||||
* @return A meta factory for the given type.
|
||||
* @tparam Type Type to reflect, if any.
|
||||
* @return An eventually generic meta factory.
|
||||
*/
|
||||
template<typename Type>
|
||||
inline meta_factory<Type> meta() ENTT_NOEXCEPT {
|
||||
return meta_factory<Type>{};
|
||||
template<typename... Type>
|
||||
inline meta_factory<Type...> meta() ENTT_NOEXCEPT {
|
||||
return meta_factory<Type...>{};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -102,7 +102,9 @@ struct meta_func_node {
|
||||
|
||||
struct meta_type_node {
|
||||
using size_type = std::size_t;
|
||||
meta_type_node * const context;
|
||||
ENTT_ID_TYPE identifier;
|
||||
meta_type_node ** hook;
|
||||
meta_type_node * next;
|
||||
meta_prop_node * prop;
|
||||
const bool is_void;
|
||||
@@ -199,23 +201,15 @@ template<>
|
||||
struct meta_node<> {
|
||||
inline static meta_type_node *local = nullptr;
|
||||
inline static meta_type_node **global = &local;
|
||||
};
|
||||
inline static meta_type_node *context = nullptr;
|
||||
|
||||
static void reset(meta_type_node *node) ENTT_NOEXCEPT {
|
||||
if(node->hook) {
|
||||
*node->hook = node->next;
|
||||
|
||||
template<typename Type>
|
||||
struct meta_node<Type> {
|
||||
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>);
|
||||
|
||||
static void reset() ENTT_NOEXCEPT {
|
||||
auto * const node = resolve();
|
||||
auto **it = meta_node<>::global;
|
||||
|
||||
while(*it && *it != node) {
|
||||
it = &(*it)->next;
|
||||
}
|
||||
|
||||
if(*it) {
|
||||
*it = (*it)->next;
|
||||
if(node->next) {
|
||||
node->next->hook = node->hook;
|
||||
}
|
||||
}
|
||||
|
||||
const auto unregister_all = y_combinator{
|
||||
@@ -237,15 +231,28 @@ struct meta_node<Type> {
|
||||
unregister_all(&node->func, &internal::meta_func_node::prop);
|
||||
|
||||
node->identifier = {};
|
||||
node->dtor = nullptr;
|
||||
node->hook = nullptr;
|
||||
node->next = nullptr;
|
||||
node->dtor = nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Type>
|
||||
struct meta_node<Type> {
|
||||
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>);
|
||||
|
||||
static meta_type_node * resolve() ENTT_NOEXCEPT {
|
||||
static meta_type_node node{
|
||||
[]() {
|
||||
auto *curr = meta_node<>::context;
|
||||
meta_node<>::context = &node;
|
||||
return curr;
|
||||
}(),
|
||||
{},
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
std::is_void_v<Type>,
|
||||
std::is_integral_v<Type>,
|
||||
std::is_floating_point_v<Type>,
|
||||
|
||||
@@ -2043,36 +2043,21 @@ TEST_F(Meta, Reset) {
|
||||
ASSERT_NE(*entt::internal::meta_info<>::global, nullptr);
|
||||
ASSERT_NE(entt::internal::meta_info<>::local, nullptr);
|
||||
|
||||
entt::meta<char>().reset();
|
||||
entt::meta<concrete_type>().reset();
|
||||
entt::meta<setter_getter_type>().reset();
|
||||
entt::meta<fat_type>().reset();
|
||||
entt::meta<data_type>().reset();
|
||||
entt::meta<func_type>().reset();
|
||||
entt::meta<array_type>().reset();
|
||||
entt::meta<double>().reset();
|
||||
entt::meta<props>().reset();
|
||||
entt::meta<base_type>().reset();
|
||||
entt::meta<derived_type>().reset();
|
||||
entt::meta<empty_type>().reset();
|
||||
entt::meta<an_abstract_type>().reset();
|
||||
entt::meta<another_abstract_type>().reset();
|
||||
entt::meta<unsigned int>().reset();
|
||||
ASSERT_TRUE(entt::resolve("char"_hs));
|
||||
ASSERT_TRUE(entt::resolve("base"_hs));
|
||||
|
||||
ASSERT_EQ(*entt::internal::meta_info<>::global, nullptr);
|
||||
ASSERT_EQ(entt::internal::meta_info<>::local, nullptr);
|
||||
entt::meta<char>().reset();
|
||||
|
||||
ASSERT_FALSE(entt::resolve("char"_hs));
|
||||
ASSERT_TRUE(entt::resolve("base"_hs));
|
||||
|
||||
entt::meta().reset();
|
||||
|
||||
ASSERT_FALSE(entt::resolve("char"_hs));
|
||||
ASSERT_FALSE(entt::resolve("base"_hs));
|
||||
ASSERT_FALSE(entt::resolve("derived"_hs));
|
||||
ASSERT_FALSE(entt::resolve("empty"_hs));
|
||||
ASSERT_FALSE(entt::resolve("fat"_hs));
|
||||
ASSERT_FALSE(entt::resolve("data"_hs));
|
||||
ASSERT_FALSE(entt::resolve("func"_hs));
|
||||
ASSERT_FALSE(entt::resolve("setter_getter"_hs));
|
||||
ASSERT_FALSE(entt::resolve("an_abstract_type"_hs));
|
||||
ASSERT_FALSE(entt::resolve("another_abstract_type"_hs));
|
||||
ASSERT_FALSE(entt::resolve("concrete"_hs));
|
||||
|
||||
ASSERT_EQ(*entt::internal::meta_info<>::global, nullptr);
|
||||
ASSERT_EQ(entt::internal::meta_info<>::local, nullptr);
|
||||
|
||||
Meta::SetUpAfterUnregistration();
|
||||
entt::meta_any any{42.};
|
||||
|
||||
@@ -56,5 +56,5 @@ LIB_EXPORT void a_module_meta_init() {
|
||||
}
|
||||
|
||||
LIB_EXPORT void a_module_meta_deinit() {
|
||||
entt::meta<char>().reset();
|
||||
entt::meta().reset();
|
||||
}
|
||||
|
||||
@@ -61,5 +61,5 @@ LIB_EXPORT void another_module_meta_init() {
|
||||
}
|
||||
|
||||
LIB_EXPORT void another_module_meta_deinit() {
|
||||
entt::meta<int>().reset();
|
||||
entt::meta().reset();
|
||||
}
|
||||
|
||||
@@ -129,8 +129,8 @@ TEST(Lib, Meta) {
|
||||
ASSERT_TRUE(entt::resolve<char>().data("c"_hs));
|
||||
|
||||
a_module_meta_deinit();
|
||||
entt::meta().reset();
|
||||
another_module_meta_deinit();
|
||||
entt::meta<double>().reset();
|
||||
|
||||
ASSERT_FALSE(entt::resolve("double"_hs));
|
||||
ASSERT_FALSE(entt::resolve("char"_hs));
|
||||
|
||||
Reference in New Issue
Block a user