meta: meta_type_node is no longer static

This commit is contained in:
Michele Caini
2022-08-27 17:04:45 +02:00
parent 443d53400d
commit 93a1d65103
23 changed files with 217 additions and 249 deletions

4
TODO
View File

@@ -11,6 +11,10 @@ DOC:
* examples (and credits) from @alanjfs :)
* update entity doc when the storage based model is in place
TODO:
* update doc (meta, lib)
* update meta natvis files
WIP:
* get rid of observers, storage based views made them pointless - document alternatives
* add storage getter for filters to views and groups

View File

@@ -1,10 +1,15 @@
#ifndef ENTT_META_CTX_HPP
#define ENTT_META_CTX_HPP
#include "../core/attribute.h"
#include <memory>
#include "../container/dense_map.hpp"
#include "../core/fwd.hpp"
#include "../core/utility.hpp"
namespace entt {
class meta_ctx;
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
@@ -14,20 +19,11 @@ namespace internal {
struct meta_type_node;
struct ENTT_API meta_context {
// we could use the lines below but VS2017 returns with an ICE if combined with ENTT_API despite the code being valid C++
// inline static meta_type_node *local = nullptr;
// inline static meta_type_node **global = &local;
struct meta_context {
dense_map<id_type, std::unique_ptr<meta_type_node>, identity> value{};
[[nodiscard]] static meta_type_node *&local() noexcept {
static meta_type_node *chain = nullptr;
return chain;
}
[[nodiscard]] static meta_type_node **&global() noexcept {
static meta_type_node **chain = &local();
return chain;
}
static inline meta_context &from(meta_ctx &ctx);
static inline const meta_context &from(const meta_ctx &ctx);
};
} // namespace internal
@@ -37,20 +33,30 @@ struct ENTT_API meta_context {
* @endcond
*/
/*! @brief Opaque container for a meta context. */
struct meta_ctx {
/**
* @brief Binds the meta system to a given context.
* @param other A valid context to which to bind.
*/
static void bind(meta_ctx other) noexcept {
internal::meta_context::global() = other.ctx;
}
private:
internal::meta_type_node **ctx{&internal::meta_context::local()};
/*! @brief Opaque meta context type. */
class meta_ctx: private internal::meta_context {
/*! @brief Attorney idiom like model to access the base class. */
friend struct internal::meta_context;
};
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
inline internal::meta_context &internal::meta_context::from(meta_ctx &ctx) {
return ctx;
}
inline const internal::meta_context &internal::meta_context::from(const meta_ctx &ctx) {
return ctx;
}
/**
* Internal details not to be documented.
* @endcond
*/
} // namespace entt
#endif

View File

@@ -19,30 +19,6 @@
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
inline void link_type_if_required(meta_type_node *owner, const id_type id) noexcept {
ENTT_ASSERT((owner->id = {}, !resolve(id)), "Duplicate identifier");
owner->id = id;
if(!resolve(id)) {
owner->next = *meta_context::global();
*meta_context::global() = owner;
}
}
} // namespace internal
/**
* Internal details not to be documented.
* @endcond
*/
/**
* @brief Meta factory to be used for reflection purposes.
*
@@ -82,7 +58,7 @@ public:
template<typename... Value>
meta_factory prop(id_type key, Value &&...value) {
(*container)[key] = internal::meta_prop_node{
&internal::meta_node<std::decay_t<Value>>::resolve...,
&internal::resolve<std::decay_t<Value>>...,
std::forward<Value>(value)...};
return *this;
@@ -108,9 +84,9 @@ class meta_factory<Type> {
/* this is never static */
(std::is_member_object_pointer_v<decltype(value_list_element_v<Index, Setter>)> && ... && std::is_const_v<std::remove_reference_t<data_type>>) ? internal::meta_traits::is_const : internal::meta_traits::is_none,
Setter::size,
&internal::meta_node<std::remove_cv_t<std::remove_reference_t<data_type>>>::resolve,
&internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>,
&meta_arg<type_list<type_list_element_t<type_list_element_t<Index, args_type>::size != 1u, type_list_element_t<Index, args_type>>...>>,
[](meta_handle instance, meta_any value) -> bool { return (meta_setter<Type, value_list_element_v<Index, Setter>>(*instance.operator->(), value.as_ref()) || ...); },
+[](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;
@@ -120,7 +96,7 @@ class meta_factory<Type> {
public:
/*! @brief Default constructor. */
meta_factory() noexcept
: owner{internal::meta_node<Type>::resolve()} {}
: owner{internal::resolve<Type>()} {}
/**
* @brief Makes a meta type _searchable_.
@@ -128,7 +104,8 @@ public:
* @return An extended meta factory for the given type.
*/
auto type(const id_type id = type_hash<Type>::value()) noexcept {
internal::link_type_if_required(owner, id);
ENTT_ASSERT(owner->id == id || !resolve(id), "Duplicate identifier");
owner->id = id;
return meta_factory<Type, decltype(internal::meta_type_node::prop)>{owner->prop};
}
@@ -145,8 +122,8 @@ public:
static_assert(!std::is_same_v<Type, Base> && std::is_base_of_v<Base, Type>, "Invalid base type");
owner->base[type_id<Base>().hash()] = internal::meta_base_node{
&internal::meta_node<Base>::resolve,
[](meta_any other) noexcept -> meta_any {
&internal::resolve<Base>,
+[](meta_any other) noexcept -> meta_any {
if(auto *ptr = other.data(); ptr) {
return forward_as_meta(*static_cast<Base *>(static_cast<Type *>(ptr)));
}
@@ -174,7 +151,7 @@ public:
using conv_type = std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<decltype(Candidate), Type &>>>;
owner->conv[type_id<conv_type>().hash()] = internal::meta_conv_node{
[](const meta_any &instance) -> meta_any {
+[](const meta_any &instance) -> meta_any {
return forward_as_meta(std::invoke(Candidate, *static_cast<const Type *>(instance.data())));
}};
@@ -195,7 +172,7 @@ public:
using conv_type = std::remove_cv_t<std::remove_reference_t<To>>;
owner->conv[type_id<conv_type>().hash()] = internal::meta_conv_node{
[](const meta_any &instance) -> meta_any {
+[](const meta_any &instance) -> meta_any {
return forward_as_meta(static_cast<To>(*static_cast<const Type *>(instance.data())));
}};
@@ -272,7 +249,7 @@ public:
template<auto Func>
auto dtor() noexcept {
static_assert(std::is_invocable_v<decltype(Func), Type &>, "The function doesn't accept an object of the type provided");
owner->dtor.dtor = [](void *instance) { std::invoke(Func, *static_cast<Type *>(instance)); };
owner->dtor.dtor = +[](void *instance) { std::invoke(Func, *static_cast<Type *>(instance)); };
return meta_factory<Type>{};
}
@@ -298,7 +275,7 @@ public:
/* this is never static */
std::is_const_v<data_type> ? internal::meta_traits::is_const : internal::meta_traits::is_none,
1u,
&internal::meta_node<std::remove_const_t<data_type>>::resolve,
&internal::resolve<std::remove_const_t<data_type>>,
&meta_arg<type_list<std::remove_const_t<data_type>>>,
&meta_setter<Type, Data>,
&meta_getter<Type, Data, Policy>};
@@ -311,7 +288,7 @@ public:
internal::meta_data_node node{
((std::is_same_v<Type, std::remove_const_t<data_type>> || std::is_const_v<data_type>) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static,
1u,
&internal::meta_node<std::remove_const_t<data_type>>::resolve,
&internal::resolve<std::remove_const_t<data_type>>,
&meta_arg<type_list<std::remove_const_t<data_type>>>,
&meta_setter<Type, Data>,
&meta_getter<Type, Data, Policy>};
@@ -351,7 +328,7 @@ public:
/* this is never static */
internal::meta_traits::is_const,
0u,
&internal::meta_node<std::remove_cv_t<std::remove_reference_t<data_type>>>::resolve,
&internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>,
&meta_arg<type_list<>>,
&meta_setter<Type, Setter>,
&meta_getter<Type, Getter, Policy>};
@@ -365,7 +342,7 @@ public:
/* this is never static nor const */
internal::meta_traits::is_none,
1u,
&internal::meta_node<std::remove_cv_t<std::remove_reference_t<data_type>>>::resolve,
&internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>,
&meta_arg<type_list<type_list_element_t<args_type::size != 1u, args_type>>>,
&meta_setter<Type, Setter>,
&meta_getter<Type, Getter, Policy>};
@@ -419,7 +396,7 @@ public:
type_id<type_list_cat_t<type_list<typename descriptor::return_type>, typename 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),
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,
&internal::resolve<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, std::remove_cv_t<std::remove_reference_t<typename descriptor::return_type>>>>,
&meta_arg<typename descriptor::args_type>,
&meta_invoke<Type, Candidate, Policy>};
@@ -458,7 +435,7 @@ private:
*/
template<typename Type>
[[nodiscard]] auto meta() noexcept {
auto *const node = internal::meta_node<Type>::resolve();
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};
}
@@ -470,25 +447,16 @@ template<typename Type>
* well as its constructors, destructors and conversion functions if any.<br/>
* Base classes aren't reset but the link between the two types is removed.
*
* The type is also removed from the list of searchable types.
* The type is also removed from the set of searchable types.
*
* @param id Unique identifier.
*/
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) {
node->id = {};
node->prop.clear();
node->ctor.clear();
node->base.clear();
node->conv.clear();
node->data.clear();
node->func.clear();
node->dtor.dtor = nullptr;
auto &&context = internal::meta_context::from(locator<meta_ctx>::value_or());
*it = std::exchange(node->next, nullptr);
break;
for(auto it = context.value.begin(); it != context.value.end(); ++it) {
if(it->second->id == id) {
it = context.value.erase(it);
}
}
}
@@ -502,18 +470,16 @@ inline void meta_reset(const id_type id) noexcept {
*/
template<typename Type>
void meta_reset() noexcept {
meta_reset(internal::meta_node<Type>::resolve()->id);
internal::meta_context::from(locator<meta_ctx>::value_or()).value.erase(type_id<Type>().hash());
}
/**
* @brief Resets all searchable types.
* @brief Resets all meta types.
*
* @sa meta_reset
*/
inline void meta_reset() noexcept {
while(*internal::meta_context::global()) {
meta_reset((*internal::meta_context::global())->id);
}
internal::meta_context::from(locator<meta_ctx>::value_or()).value.clear();
}
} // namespace entt

View File

@@ -45,7 +45,7 @@ public:
*/
template<typename Type>
meta_sequence_container(std::in_place_type_t<Type>, any instance) noexcept
: value_type_node{&internal::meta_node<typename Type::value_type>::resolve},
: value_type_node{&internal::resolve<typename Type::value_type>},
size_fn{&meta_sequence_container_traits<Type>::size},
resize_fn{&meta_sequence_container_traits<Type>::resize},
iter_fn{&meta_sequence_container_traits<Type>::iter},
@@ -93,9 +93,9 @@ public:
template<typename Type>
meta_associative_container(std::in_place_type_t<Type>, any instance) noexcept
: key_only_container{meta_associative_container_traits<Type>::key_only},
key_type_node{&internal::meta_node<typename Type::key_type>::resolve},
key_type_node{&internal::resolve<typename Type::key_type>},
mapped_type_node{nullptr},
value_type_node{&internal::meta_node<typename Type::value_type>::resolve},
value_type_node{&internal::resolve<typename Type::value_type>},
size_fn{&meta_associative_container_traits<Type>::size},
clear_fn{&meta_associative_container_traits<Type>::clear},
iter_fn{&meta_associative_container_traits<Type>::iter},
@@ -103,7 +103,7 @@ public:
find_fn{&meta_associative_container_traits<Type>::find},
storage{std::move(instance)} {
if constexpr(!meta_associative_container_traits<Type>::key_only) {
mapped_type_node = &internal::meta_node<typename Type::mapped_type>::resolve;
mapped_type_node = &internal::resolve<typename Type::mapped_type>;
}
}
@@ -207,7 +207,7 @@ public:
template<typename Type, typename... Args>
explicit meta_any(std::in_place_type_t<Type>, Args &&...args)
: storage{std::in_place_type<Type>, std::forward<Args>(args)...},
node{internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve()},
node{internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>()},
vtable{&basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>} {}
/**
@@ -218,7 +218,7 @@ public:
template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
meta_any(Type &&value)
: storage{std::forward<Type>(value)},
node{internal::meta_node<std::decay_t<Type>>::resolve()},
node{internal::resolve<std::decay_t<Type>>()},
vtable{&basic_vtable<std::decay_t<Type>>} {}
/**
@@ -430,7 +430,7 @@ public:
if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
return meta_any{};
} else {
return allow_cast(internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve());
return allow_cast(internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>());
}
}
@@ -442,9 +442,9 @@ public:
template<typename Type>
bool allow_cast() {
if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
return allow_cast(internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve()) && (storage.data() != nullptr);
return allow_cast(internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>()) && (storage.data() != nullptr);
} else {
return allow_cast(internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve());
return allow_cast(internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>());
}
}
@@ -454,7 +454,7 @@ public:
release();
vtable = &basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
storage.emplace<Type>(std::forward<Args>(args)...);
node = internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve();
node = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>();
}
/*! @copydoc any::assign */

View File

@@ -12,6 +12,8 @@
#include "../core/type_info.hpp"
#include "../core/type_traits.hpp"
#include "../core/utility.hpp"
#include "../locator/locator.hpp"
#include "context.hpp"
#include "type_traits.hpp"
namespace entt {
@@ -109,13 +111,12 @@ struct meta_type_node {
const type_info *info;
id_type id;
const meta_traits traits;
meta_type_node *next;
const size_type size_of;
meta_type_node *(*const remove_pointer)() noexcept;
meta_any (*const default_constructor)();
double (*const conversion_helper)(void *, const void *);
meta_any (*const from_void)(void *, const void *);
meta_traits traits;
size_type size_of;
meta_type_node *(*remove_pointer)() noexcept;
meta_any (*default_constructor)();
double (*conversion_helper)(void *, const void *);
meta_any (*from_void)(void *, const void *);
meta_template_node templ;
dense_map<id_type, meta_prop_node, identity> prop{};
dense_map<id_type, meta_ctor_node, identity> ctor{};
@@ -126,67 +127,87 @@ struct meta_type_node {
meta_dtor_node dtor{};
};
template<typename Type>
meta_type_node *resolve() noexcept;
template<typename... Args>
meta_type_node *meta_arg_node(type_list<Args...>, const std::size_t index) noexcept;
[[nodiscard]] meta_type_node *meta_arg_node(type_list<Args...>, const std::size_t index) noexcept {
meta_type_node *args[sizeof...(Args) + 1u]{nullptr, internal::resolve<std::remove_cv_t<std::remove_reference_t<Args>>>()...};
return args[index + 1u];
}
template<typename Type>
class ENTT_API meta_node {
[[nodiscard]] auto *meta_default_constructor() noexcept {
static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");
[[nodiscard]] static auto *meta_default_constructor() noexcept {
if constexpr(std::is_default_constructible_v<Type>) {
return +[]() { return meta_any{std::in_place_type<Type>}; };
} else {
return static_cast<std::decay_t<decltype(meta_type_node::default_constructor)>>(nullptr);
}
if constexpr(std::is_default_constructible_v<Type>) {
return +[]() { return meta_any{std::in_place_type<Type>}; };
} else {
return static_cast<std::decay_t<decltype(meta_type_node::default_constructor)>>(nullptr);
}
}
[[nodiscard]] static auto *meta_conversion_helper() noexcept {
if constexpr(std::is_arithmetic_v<Type>) {
return +[](void *bin, const void *value) {
return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(*static_cast<const double *>(value))) : static_cast<double>(*static_cast<const Type *>(value));
};
} else if constexpr(std::is_enum_v<Type>) {
return +[](void *bin, const void *value) {
return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(static_cast<std::underlying_type_t<Type>>(*static_cast<const double *>(value)))) : static_cast<double>(*static_cast<const Type *>(value));
};
} else {
return static_cast<std::decay_t<decltype(meta_type_node::conversion_helper)>>(nullptr);
}
template<typename Type>
[[nodiscard]] auto *meta_conversion_helper() noexcept {
static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");
if constexpr(std::is_arithmetic_v<Type>) {
return +[](void *bin, const void *value) {
return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(*static_cast<const double *>(value))) : static_cast<double>(*static_cast<const Type *>(value));
};
} else if constexpr(std::is_enum_v<Type>) {
return +[](void *bin, const void *value) {
return bin ? static_cast<double>(*static_cast<Type *>(bin) = static_cast<Type>(static_cast<std::underlying_type_t<Type>>(*static_cast<const double *>(value)))) : static_cast<double>(*static_cast<const Type *>(value));
};
} else {
return static_cast<std::decay_t<decltype(meta_type_node::conversion_helper)>>(nullptr);
}
}
[[nodiscard]] static auto *meta_from_void() noexcept {
if constexpr(std::is_same_v<Type, void> || std::is_function_v<Type>) {
return static_cast<std::decay_t<decltype(meta_type_node::from_void)>>(nullptr);
} else {
return +[](void *element, const void *as_const) {
using value_type = std::decay_t<Type>;
template<typename Type>
[[nodiscard]] auto *meta_from_void() noexcept {
static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");
if(element) {
return meta_any{std::in_place_type<value_type &>, *static_cast<value_type *>(element)};
}
if constexpr(std::is_same_v<Type, void> || std::is_function_v<Type>) {
return static_cast<std::decay_t<decltype(meta_type_node::from_void)>>(nullptr);
} else {
return +[](void *element, const void *as_const) {
using value_type = std::decay_t<Type>;
return meta_any{std::in_place_type<const value_type &>, *static_cast<const value_type *>(as_const)};
};
}
if(element) {
return meta_any{std::in_place_type<value_type &>, *static_cast<value_type *>(element)};
}
return meta_any{std::in_place_type<const value_type &>, *static_cast<const value_type *>(as_const)};
};
}
}
[[nodiscard]] static auto meta_template_info() noexcept {
if constexpr(is_complete_v<meta_template_traits<Type>>) {
return meta_template_node{
meta_template_traits<Type>::args_type::size,
&meta_node<typename meta_template_traits<Type>::class_type>::resolve,
+[](const std::size_t index) noexcept -> meta_type_node * { return meta_arg_node(typename meta_template_traits<Type>::args_type{}, index); }};
} else {
return meta_template_node{};
}
template<typename Type>
[[nodiscard]] auto meta_template_info() noexcept {
static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");
if constexpr(is_complete_v<meta_template_traits<Type>>) {
return meta_template_node{
meta_template_traits<Type>::args_type::size,
&resolve<typename meta_template_traits<Type>::class_type>,
+[](const std::size_t index) noexcept -> meta_type_node * { return meta_arg_node(typename meta_template_traits<Type>::args_type{}, index); }};
} else {
return meta_template_node{};
}
}
public:
[[nodiscard]] static meta_type_node *resolve() noexcept {
static meta_type_node node{
template<typename Type>
[[nodiscard]] meta_type_node *resolve() noexcept {
static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");
auto &&context = meta_context::from(locator<meta_ctx>::value_or());
auto it = context.value.find(type_id<Type>().hash());
if(it == context.value.end()) {
meta_type_node node{
&type_id<Type>(),
{},
type_id<Type>().hash(),
(std::is_arithmetic_v<Type> ? internal::meta_traits::is_arithmetic : internal::meta_traits::is_none)
| (std::is_integral_v<Type> ? internal::meta_traits::is_integral : internal::meta_traits::is_none)
| (std::is_signed_v<Type> ? internal::meta_traits::is_signed : internal::meta_traits::is_none)
@@ -196,24 +217,17 @@ public:
| (is_meta_pointer_like_v<Type> ? internal::meta_traits::is_meta_pointer_like : internal::meta_traits::is_none)
| (is_complete_v<meta_sequence_container_traits<Type>> ? internal::meta_traits::is_meta_sequence_container : internal::meta_traits::is_none)
| (is_complete_v<meta_associative_container_traits<Type>> ? internal::meta_traits::is_meta_associative_container : internal::meta_traits::is_none),
nullptr,
size_of_v<Type>,
&meta_node<std::remove_cv_t<std::remove_pointer_t<Type>>>::resolve,
meta_default_constructor(),
meta_conversion_helper(),
meta_from_void(),
meta_template_info()
// tricks clang-format
};
&resolve<std::remove_cv_t<std::remove_pointer_t<Type>>>,
meta_default_constructor<Type>(),
meta_conversion_helper<Type>(),
meta_from_void<Type>(),
meta_template_info<Type>()};
return &node;
it = context.value.insert_or_assign(node.info->hash(), std::make_unique<meta_type_node>(std::move(node))).first;
}
};
template<typename... Args>
[[nodiscard]] meta_type_node *meta_arg_node(type_list<Args...>, const std::size_t index) noexcept {
meta_type_node *args[sizeof...(Args) + 1u]{nullptr, internal::meta_node<std::remove_cv_t<std::remove_reference_t<Args>>>::resolve()...};
return args[index + 1u];
return it->second.get();
}
} // namespace internal

View File

@@ -16,52 +16,19 @@ namespace entt {
namespace internal {
template<typename Type, typename Node>
struct old_meta_range_iterator final {
using difference_type = std::ptrdiff_t;
using value_type = Type;
using pointer = input_iterator_pointer<value_type>;
using reference = value_type;
using iterator_category = std::input_iterator_tag;
using node_type = Node;
old_meta_range_iterator() noexcept
: it{} {}
old_meta_range_iterator(node_type *head) noexcept
: it{head} {}
old_meta_range_iterator &operator++() noexcept {
return (it = it->next), *this;
}
old_meta_range_iterator operator++(int) noexcept {
old_meta_range_iterator orig = *this;
return ++(*this), orig;
}
[[nodiscard]] reference operator*() const noexcept {
return it;
}
[[nodiscard]] pointer operator->() const noexcept {
return operator*();
}
[[nodiscard]] bool operator==(const old_meta_range_iterator &other) const noexcept {
return it == other.it;
}
[[nodiscard]] bool operator!=(const old_meta_range_iterator &other) const noexcept {
return !(*this == other);
}
private:
node_type *it;
};
template<typename Type, typename It>
struct meta_range_iterator final {
class meta_range_iterator final {
template<typename Value>
auto to_value(int, const Value &value) const -> decltype(*value, Type{}) {
return &*it->second;
}
template<typename Value>
Type to_value(char, const Value &value) const {
return &it->second;
}
public:
using difference_type = std::ptrdiff_t;
using value_type = std::pair<id_type, Type>;
using pointer = input_iterator_pointer<value_type>;
@@ -84,7 +51,7 @@ struct meta_range_iterator final {
}
[[nodiscard]] reference operator*() const noexcept {
return std::make_pair(it->first, &it->second);
return std::make_pair(it->first, to_value(0, it->second));
}
[[nodiscard]] pointer operator->() const noexcept {
@@ -110,14 +77,6 @@ private:
* @endcond
*/
/**
* @brief Iterable range to use to iterate all types of meta objects.
* @tparam Type Type of meta objects returned.
* @tparam Node Type of meta nodes iterated.
*/
template<typename Type, typename Node = typename Type::node_type>
using old_meta_range = iterable_adaptor<internal::old_meta_range_iterator<Type, Node>>;
/**
* @brief Iterable range to use to iterate all types of meta objects.
* @tparam Type Type of meta objects returned.

View File

@@ -3,6 +3,7 @@
#include <type_traits>
#include "../core/type_info.hpp"
#include "../locator/locator.hpp"
#include "context.hpp"
#include "meta.hpp"
#include "node.hpp"
@@ -17,15 +18,16 @@ namespace entt {
*/
template<typename Type>
[[nodiscard]] meta_type resolve() noexcept {
return internal::meta_node<std::remove_cv_t<std::remove_reference_t<Type>>>::resolve();
return internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>();
}
/**
* @brief Returns a range to use to visit all meta types.
* @return An iterable range to use to visit all meta types.
*/
[[nodiscard]] inline old_meta_range<meta_type> resolve() noexcept {
return {*internal::meta_context::global(), nullptr};
[[nodiscard]] inline meta_range<meta_type, typename decltype(internal::meta_context::value)::const_iterator> resolve() noexcept {
auto &&context = internal::meta_context::from(locator<meta_ctx>::value_or());
return {context.value.cbegin(), context.value.cend()};
}
/**
@@ -35,8 +37,8 @@ template<typename Type>
*/
[[nodiscard]] inline meta_type resolve(const id_type id) noexcept {
for(auto &&curr: resolve()) {
if(curr.id() == id) {
return curr;
if(curr.second.id() == id) {
return curr.second;
}
}
@@ -49,10 +51,10 @@ template<typename Type>
* @return The meta type associated with the given type info object, if any.
*/
[[nodiscard]] inline meta_type resolve(const type_info &info) noexcept {
for(auto &&curr: resolve()) {
if(curr.info() == info) {
return curr;
}
auto &&context = internal::meta_context::from(locator<meta_ctx>::value_or());
if(auto it = context.value.find(info.hash()); it != context.value.cend()) {
return it->second.get();
}
return {};

View File

@@ -181,7 +181,7 @@ TEST_F(MetaBase, TransferWithMutatingThis) {
TEST_F(MetaBase, ReRegistration) {
SetUp();
auto *node = entt::internal::meta_node<derived_t>::resolve();
auto *node = entt::internal::resolve<derived_t>();
ASSERT_FALSE(node->base.empty());
ASSERT_EQ(node->base.size(), 2u);

View File

@@ -62,7 +62,7 @@ TEST_F(MetaConv, Functionalities) {
TEST_F(MetaConv, ReRegistration) {
SetUp();
auto *node = entt::internal::meta_node<clazz_t>::resolve();
auto *node = entt::internal::resolve<clazz_t>();
ASSERT_FALSE(node->conv.empty());
ASSERT_EQ(node->conv.size(), 3u);

View File

@@ -205,7 +205,7 @@ TEST_F(MetaCtor, NonDefaultConstructibleType) {
TEST_F(MetaCtor, ReRegistration) {
SetUp();
auto *node = entt::internal::meta_node<double>::resolve();
auto *node = entt::internal::resolve<double>();
ASSERT_NE(node->ctor, nullptr);
// implicitly generated default constructor is not cleared

View File

@@ -643,7 +643,7 @@ TEST_F(MetaData, ReRegistration) {
SetUp();
auto *node = entt::internal::meta_node<base_t>::resolve();
auto *node = entt::internal::resolve<base_t>();
auto type = entt::resolve<base_t>();
ASSERT_FALSE(node->data.empty());

View File

@@ -101,7 +101,7 @@ TEST_F(MetaDtor, AsRefConstruction) {
TEST_F(MetaDtor, ReRegistration) {
SetUp();
auto *node = entt::internal::meta_node<clazz_t>::resolve();
auto *node = entt::internal::resolve<clazz_t>();
ASSERT_NE(node->dtor.dtor, nullptr);

View File

@@ -86,7 +86,7 @@ TEST_F(MetaProp, ReRegistration) {
SetUp();
auto *node = entt::internal::meta_node<base_1_t>::resolve();
auto *node = entt::internal::resolve<base_1_t>();
auto type = entt::resolve<base_1_t>();
ASSERT_FALSE(node->prop.empty());

View File

@@ -1,6 +1,7 @@
#include <type_traits>
#include <gtest/gtest.h>
#include <entt/core/hashed_string.hpp>
#include <entt/locator/locator.hpp>
#include <entt/meta/factory.hpp>
#include <entt/meta/meta.hpp>
#include <entt/meta/range.hpp>
@@ -22,21 +23,22 @@ struct MetaRange: ::testing::Test {
TEST_F(MetaRange, Range) {
using namespace entt::literals;
entt::old_meta_range<entt::meta_type> range{entt::internal::meta_context::local(), nullptr};
auto range = entt::resolve();
auto it = range.begin();
ASSERT_NE(it, range.end());
ASSERT_TRUE(it != range.end());
ASSERT_FALSE(it == range.end());
ASSERT_EQ(it->info(), entt::resolve<double>().info());
ASSERT_EQ((++it)->info(), entt::resolve("int"_hs).info());
ASSERT_EQ((it++)->info(), entt::resolve<int>().info());
ASSERT_EQ(it->second.info(), entt::resolve<int>().info());
ASSERT_EQ((++it)->second.info(), entt::resolve("double"_hs).info());
ASSERT_EQ((it++)->second.info(), entt::resolve<double>().info());
ASSERT_EQ(it, range.end());
}
TEST_F(MetaRange, EmptyRange) {
entt::old_meta_range<entt::meta_data> range{};
entt::meta_reset();
auto range = entt::resolve();
ASSERT_EQ(range.begin(), range.end());
}

View File

@@ -5,6 +5,7 @@
#include <vector>
#include <gtest/gtest.h>
#include <entt/core/hashed_string.hpp>
#include <entt/locator/locator.hpp>
#include <entt/core/type_info.hpp>
#include <entt/core/utility.hpp>
#include <entt/meta/container.hpp>
@@ -191,15 +192,15 @@ TEST_F(MetaType, Resolve) {
auto range = entt::resolve();
// it could be "char"_hs rather than entt::hashed_string::value("char") if it weren't for a bug in VS2017
const auto it = std::find_if(range.begin(), range.end(), [](auto type) { return type.id() == entt::hashed_string::value("clazz"); });
const auto it = std::find_if(range.begin(), range.end(), [](auto curr) { return curr.second.id() == entt::hashed_string::value("clazz"); });
ASSERT_NE(it, range.end());
ASSERT_EQ(*it, entt::resolve<clazz_t>());
ASSERT_EQ(it->second, entt::resolve<clazz_t>());
bool found = false;
for(auto curr: entt::resolve()) {
found = found || curr == entt::resolve<double>();
found = found || curr.second == entt::resolve<double>();
}
ASSERT_TRUE(found);
@@ -637,7 +638,7 @@ TEST_F(MetaType, PropertiesAndCornerCases) {
TEST_F(MetaType, ResetAndReRegistrationAfterReset) {
using namespace entt::literals;
ASSERT_NE(*entt::internal::meta_context::global(), nullptr);
ASSERT_FALSE(entt::internal::meta_context::from(entt::locator<entt::meta_ctx>::value_or()).value.empty());
entt::meta_reset<double>();
entt::meta_reset<unsigned int>();
@@ -654,7 +655,7 @@ TEST_F(MetaType, ResetAndReRegistrationAfterReset) {
ASSERT_FALSE(entt::resolve("derived"_hs));
ASSERT_FALSE(entt::resolve("clazz"_hs));
ASSERT_EQ(*entt::internal::meta_context::global(), nullptr);
ASSERT_TRUE(entt::internal::meta_context::from(entt::locator<entt::meta_ctx>::value_or()).value.empty());
ASSERT_FALSE(entt::resolve<clazz_t>().prop(static_cast<entt::id_type>(property_t::value)));
// implicitly generated default constructor is not cleared
@@ -687,14 +688,14 @@ TEST_F(MetaType, ReRegistration) {
int count = 0;
for(auto type: entt::resolve()) {
count += static_cast<bool>(type);
for([[maybe_unused]] auto type: entt::resolve()) {
++count;
}
SetUp();
for(auto type: entt::resolve()) {
count -= static_cast<bool>(type);
for([[maybe_unused]] auto type: entt::resolve()) {
--count;
}
ASSERT_EQ(count, 0);

View File

@@ -8,6 +8,10 @@ position create_position(int x, int y) {
return position{x, y};
}
ENTT_API void share(entt::locator<entt::meta_ctx>::node_type handle) {
entt::locator<entt::meta_ctx>::reset(handle);
}
ENTT_API void set_up() {
using namespace entt::literals;

View File

@@ -6,6 +6,7 @@
#include <entt/meta/resolve.hpp>
#include "types.h"
ENTT_API void share(entt::locator<entt::meta_ctx>::node_type);
ENTT_API void set_up();
ENTT_API void tear_down();
ENTT_API entt::meta_any wrap_int(int);
@@ -16,6 +17,7 @@ TEST(Lib, Meta) {
ASSERT_FALSE(entt::resolve("position"_hs));
ASSERT_FALSE(entt::resolve("velocity"_hs));
share(entt::locator<entt::meta_ctx>::handle());
set_up();
entt::meta<double>().conv<int>();
@@ -40,6 +42,9 @@ TEST(Lib, Meta) {
ASSERT_EQ(vel.type().data("dx"_hs).get(vel).cast<double>(), 0.);
ASSERT_EQ(vel.type().data("dy"_hs).get(vel).cast<double>(), 0.);
pos.reset();
vel.reset();
ASSERT_EQ(wrap_int(42).type(), entt::resolve<int>());
ASSERT_EQ(wrap_int(42).cast<int>(), 42);

View File

@@ -3,6 +3,7 @@
#include <gtest/gtest.h>
#include <cr.h>
#include <entt/core/hashed_string.hpp>
#include <entt/locator/locator.hpp>
#include <entt/meta/factory.hpp>
#include <entt/meta/meta.hpp>
#include <entt/meta/resolve.hpp>
@@ -14,6 +15,7 @@ TEST(Lib, Meta) {
ASSERT_FALSE(entt::resolve("position"_hs));
userdata ud{};
ud.ctx = entt::locator<entt::meta_ctx>::handle();
cr_plugin ctx;
cr_plugin_load(ctx, PLUGIN);

View File

@@ -1,5 +1,6 @@
#include <cr.h>
#include <entt/core/hashed_string.hpp>
#include <entt/locator/locator.hpp>
#include <entt/meta/context.hpp>
#include <entt/meta/factory.hpp>
#include <entt/meta/meta.hpp>
@@ -33,7 +34,7 @@ void tear_down() {
CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
switch(operation) {
case CR_LOAD:
entt::meta_ctx::bind(static_cast<userdata *>(ctx->userdata)->ctx);
entt::locator<entt::meta_ctx>::reset(static_cast<userdata *>(ctx->userdata)->ctx);
set_up();
break;
case CR_STEP:

View File

@@ -1,6 +1,7 @@
#ifndef ENTT_LIB_META_PLUGIN_TYPES_H
#define ENTT_LIB_META_PLUGIN_TYPES_H
#include <entt/locator/locator.hpp>
#include <entt/meta/meta.hpp>
struct position {
@@ -14,7 +15,7 @@ struct velocity {
};
struct userdata {
entt::meta_ctx ctx;
entt::locator<entt::meta_ctx>::node_type ctx;
entt::meta_any any;
};

View File

@@ -14,6 +14,7 @@ TEST(Lib, Meta) {
ASSERT_FALSE(entt::resolve("position"_hs));
userdata ud{};
ud.ctx = entt::locator<entt::meta_ctx>::handle();
cr_plugin ctx;
cr_plugin_load(ctx, PLUGIN);

View File

@@ -33,7 +33,7 @@ void tear_down() {
CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
switch(operation) {
case CR_LOAD:
entt::meta_ctx::bind(static_cast<userdata *>(ctx->userdata)->ctx);
entt::locator<entt::meta_ctx>::reset(static_cast<userdata *>(ctx->userdata)->ctx);
set_up();
break;
case CR_STEP:

View File

@@ -15,7 +15,7 @@ struct custom_type_hash;
static constexpr entt::id_type value() noexcept { \
return entt::basic_hashed_string<std::remove_const_t<std::remove_pointer_t<std::decay_t<decltype(#clazz)>>>>{#clazz}; \
} \
};
}
struct position {
int x;
@@ -28,7 +28,7 @@ struct velocity {
};
struct userdata {
entt::meta_ctx ctx;
entt::locator<entt::meta_ctx>::node_type ctx;
entt::meta_any any;
};