meta: improved perf and compilation time, reduced loc
This commit is contained in:
4
TODO
4
TODO
@@ -37,4 +37,6 @@
|
||||
* is it possible to make named type constraints namespace-free?
|
||||
* stomp -> merge (naming is hard as heck, it's known thing)
|
||||
* observer: user defined filters (eg .replace<T, &function> or .group<T, U, &func>)
|
||||
* use meta_handle for inputs to invoke/ctor/...
|
||||
* any-of rule for views/groups (eg entity has A and any of B/C/D)
|
||||
* meta
|
||||
- update doc
|
||||
|
||||
@@ -417,10 +417,10 @@ There are a few alternatives available at the moment:
|
||||
```
|
||||
|
||||
* The _as-alias_ policy, associated with the type `entt::as_alias_t`.<br/>
|
||||
It allows to build wrappers that act as aliases for the objects used to
|
||||
initialize them. Modifying the object contained in the wrapper for which the
|
||||
_aliasing_ was requested will make it possible to directly modify the instance
|
||||
used to initialize the wrapper itself.<br/>
|
||||
It allows to build wrappers that act as aliases for the objects that generated
|
||||
them. Modifying the object contained in the wrapper for which the _aliasing_
|
||||
was requested will make it possible to directly modify the instance used to
|
||||
initialize the wrapper itself.<br/>
|
||||
This policy works with constructors (for example, when objects are taken from
|
||||
an external container rather than created on demand), data members and
|
||||
functions in general (as long as their return types are lvalue references).
|
||||
|
||||
@@ -86,7 +86,7 @@ meta_any construct(meta_any * const args, std::index_sequence<Indexes...>) {
|
||||
|
||||
|
||||
template<bool Const, typename Type, auto Data>
|
||||
bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index, [[maybe_unused]] meta_any value) {
|
||||
bool setter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any index, [[maybe_unused]] meta_any value) {
|
||||
bool accepted = false;
|
||||
|
||||
if constexpr(!Const) {
|
||||
@@ -94,7 +94,7 @@ bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index
|
||||
using helper_type = meta_function_helper_t<decltype(Data)>;
|
||||
using data_type = std::tuple_element_t<!std::is_member_function_pointer_v<decltype(Data)>, typename helper_type::args_type>;
|
||||
static_assert(std::is_invocable_v<decltype(Data), Type &, data_type>);
|
||||
auto * const clazz = meta_any{handle}.try_cast<Type>();
|
||||
auto * const clazz = instance.try_cast<Type>();
|
||||
auto * const direct = value.try_cast<data_type>();
|
||||
|
||||
if(clazz && (direct || value.convert<data_type>())) {
|
||||
@@ -104,7 +104,7 @@ bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index
|
||||
} else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
|
||||
using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
|
||||
static_assert(std::is_invocable_v<decltype(Data), Type *>);
|
||||
auto * const clazz = meta_any{handle}.try_cast<Type>();
|
||||
auto * const clazz = instance.try_cast<Type>();
|
||||
|
||||
if constexpr(std::is_array_v<data_type>) {
|
||||
using underlying_type = std::remove_extent_t<data_type>;
|
||||
@@ -152,7 +152,7 @@ bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index
|
||||
|
||||
|
||||
template<typename Type, auto Data, typename Policy>
|
||||
meta_any getter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index) {
|
||||
meta_any getter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any index) {
|
||||
auto dispatch = [](auto &&value) {
|
||||
if constexpr(std::is_same_v<Policy, as_void_t>) {
|
||||
return meta_any{std::in_place_type<void>};
|
||||
@@ -166,12 +166,12 @@ meta_any getter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any i
|
||||
|
||||
if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>> || std::is_member_function_pointer_v<decltype(Data)>) {
|
||||
static_assert(std::is_invocable_v<decltype(Data), Type &>);
|
||||
auto * const clazz = meta_any{handle}.try_cast<Type>();
|
||||
auto * const clazz = instance.try_cast<Type>();
|
||||
return clazz ? dispatch(std::invoke(Data, *clazz)) : meta_any{};
|
||||
} else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
|
||||
using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
|
||||
static_assert(std::is_invocable_v<decltype(Data), Type *>);
|
||||
auto * const clazz = meta_any{handle}.try_cast<Type>();
|
||||
auto * const clazz = instance.try_cast<Type>();
|
||||
|
||||
if constexpr(std::is_array_v<data_type>) {
|
||||
auto * const idx = index.try_cast<std::size_t>();
|
||||
@@ -193,7 +193,7 @@ meta_any getter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any i
|
||||
|
||||
|
||||
template<typename Type, auto Candidate, typename Policy, std::size_t... Indexes>
|
||||
meta_any invoke([[maybe_unused]] meta_handle handle, meta_any *args, std::index_sequence<Indexes...>) {
|
||||
meta_any invoke([[maybe_unused]] meta_any instance, meta_any *args, std::index_sequence<Indexes...>) {
|
||||
using helper_type = meta_function_helper_t<decltype(Candidate)>;
|
||||
|
||||
auto dispatch = [](auto *... params) {
|
||||
@@ -221,7 +221,7 @@ meta_any invoke([[maybe_unused]] meta_handle handle, meta_any *args, std::index_
|
||||
if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Candidate)>>>) {
|
||||
return (std::get<Indexes>(direct) && ...) ? dispatch(std::get<Indexes>(direct)...) : meta_any{};
|
||||
} else {
|
||||
auto * const clazz = meta_any{handle}.try_cast<Type>();
|
||||
auto * const clazz = instance.try_cast<Type>();
|
||||
return (clazz && (std::get<Indexes>(direct) && ...)) ? dispatch(clazz, std::get<Indexes>(direct)...) : meta_any{};
|
||||
}
|
||||
}
|
||||
@@ -604,14 +604,10 @@ public:
|
||||
|
||||
static internal::meta_dtor_node node{
|
||||
type,
|
||||
[](meta_handle handle) {
|
||||
const auto valid = (handle.type() == internal::meta_info<Type>::resolve());
|
||||
|
||||
if(valid) {
|
||||
std::invoke(Func, *meta_any{handle}.try_cast<Type>());
|
||||
[](void *instance) {
|
||||
if(instance) {
|
||||
std::invoke(Func, *static_cast<Type *>(instance));
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -650,8 +646,8 @@ public:
|
||||
true,
|
||||
true,
|
||||
&internal::meta_info<Type>::resolve,
|
||||
[](meta_handle, meta_any, meta_any) { return false; },
|
||||
[](meta_handle, meta_any) -> meta_any { return Data; }
|
||||
[](meta_any, meta_any, meta_any) { return false; },
|
||||
[](meta_any, meta_any) -> meta_any { return Data; }
|
||||
};
|
||||
|
||||
curr = &node;
|
||||
@@ -774,8 +770,8 @@ public:
|
||||
!std::is_member_function_pointer_v<decltype(Candidate)>,
|
||||
&internal::meta_info<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, typename helper_type::return_type>>::resolve,
|
||||
&helper_type::arg,
|
||||
[](meta_handle handle, meta_any *any) {
|
||||
return internal::invoke<Type, Candidate, Policy>(handle, any, helper_type::index_sequence);
|
||||
[](meta_any instance, meta_any *args) {
|
||||
return internal::invoke<Type, Candidate, Policy>(std::move(instance), args, helper_type::index_sequence);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
#define ENTT_META_META_HPP
|
||||
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include "../config/config.h"
|
||||
#include "../core/type_traits.hpp"
|
||||
@@ -15,7 +15,6 @@ namespace entt {
|
||||
|
||||
|
||||
class meta_any;
|
||||
class meta_handle;
|
||||
class meta_type;
|
||||
|
||||
|
||||
@@ -67,7 +66,7 @@ struct meta_ctor_node {
|
||||
|
||||
struct meta_dtor_node {
|
||||
meta_type_node * const parent;
|
||||
bool(* const invoke)(meta_handle);
|
||||
void(* const invoke)(void *);
|
||||
};
|
||||
|
||||
|
||||
@@ -79,8 +78,8 @@ struct meta_data_node {
|
||||
const bool is_const;
|
||||
const bool is_static;
|
||||
meta_type_node *(* const type)() ENTT_NOEXCEPT;
|
||||
bool(* const set)(meta_handle, meta_any, meta_any);
|
||||
meta_any(* const get)(meta_handle, meta_any);
|
||||
bool(* const set)(meta_any, meta_any, meta_any);
|
||||
meta_any(* const get)(meta_any, meta_any);
|
||||
};
|
||||
|
||||
|
||||
@@ -95,7 +94,7 @@ struct meta_func_node {
|
||||
const bool is_static;
|
||||
meta_type_node *(* const ret)() ENTT_NOEXCEPT;
|
||||
meta_type_node *(* const arg)(size_type) ENTT_NOEXCEPT;
|
||||
meta_any(* const invoke)(meta_handle, meta_any *);
|
||||
meta_any(* const invoke)(meta_any, meta_any *);
|
||||
};
|
||||
|
||||
|
||||
@@ -303,9 +302,6 @@ struct meta_info: meta_node<std::remove_cv_t<std::remove_reference_t<Type>>...>
|
||||
* constructible.
|
||||
*/
|
||||
class meta_any {
|
||||
/*! @brief A meta handle is allowed to _inherit_ from a meta any. */
|
||||
friend class meta_handle;
|
||||
|
||||
using storage_type = std::aligned_storage_t<sizeof(void *), alignof(void *)>;
|
||||
using copy_fn_type = void(meta_any &, const meta_any &);
|
||||
using steal_fn_type = void(meta_any &, meta_any &);
|
||||
@@ -321,9 +317,8 @@ class meta_any {
|
||||
|
||||
static void destroy(meta_any &any) {
|
||||
const auto * const node = internal::meta_info<Type>::resolve();
|
||||
[[maybe_unused]] const bool destroyed = (!node->dtor || node->dtor->invoke(any));
|
||||
if(node->dtor) { node->dtor->invoke(any.instance); }
|
||||
delete static_cast<Type *>(any.instance);
|
||||
ENTT_ASSERT(destroyed);
|
||||
}
|
||||
|
||||
static void copy(meta_any &to, const meta_any &from) {
|
||||
@@ -347,9 +342,8 @@ class meta_any {
|
||||
|
||||
static void destroy(meta_any &any) {
|
||||
const auto * const node = internal::meta_info<Type>::resolve();
|
||||
[[maybe_unused]] const bool destroyed = (!node->dtor || node->dtor->invoke(any));
|
||||
if(node->dtor) { node->dtor->invoke(any.instance); }
|
||||
static_cast<Type *>(any.instance)->~Type();
|
||||
ENTT_ASSERT(destroyed);
|
||||
}
|
||||
|
||||
static void copy(meta_any &to, const meta_any &from) {
|
||||
@@ -362,6 +356,13 @@ class meta_any {
|
||||
}
|
||||
};
|
||||
|
||||
meta_any(const internal::meta_type_node *curr, void *ref) ENTT_NOEXCEPT
|
||||
: meta_any{}
|
||||
{
|
||||
node = curr;
|
||||
instance = ref;
|
||||
}
|
||||
|
||||
public:
|
||||
/*! @brief Default constructor. */
|
||||
meta_any() ENTT_NOEXCEPT = default;
|
||||
@@ -391,30 +392,21 @@ public:
|
||||
/**
|
||||
* @brief Constructs a meta any that holds an unmanaged object.
|
||||
* @tparam Type Type of object to use to initialize the container.
|
||||
* @param type An instance of an object to use to initialize the container.
|
||||
* @param value An instance of an object to use to initialize the container.
|
||||
*/
|
||||
template<typename Type>
|
||||
explicit meta_any(std::reference_wrapper<Type> type)
|
||||
: meta_any{}
|
||||
{
|
||||
node = internal::meta_info<Type>::resolve();
|
||||
instance = &type.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructs a meta any from a meta handle object.
|
||||
* @param handle A reference to an object to use to initialize the meta any.
|
||||
*/
|
||||
inline meta_any(meta_handle handle) ENTT_NOEXCEPT;
|
||||
meta_any(std::reference_wrapper<Type> value)
|
||||
: meta_any{internal::meta_info<Type>::resolve(), &value.get()}
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Constructs a meta any from a given value.
|
||||
* @tparam Type Type of object to use to initialize the container.
|
||||
* @param type An instance of an object to use to initialize the container.
|
||||
* @param value An instance of an object to use to initialize the container.
|
||||
*/
|
||||
template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_any>>>
|
||||
meta_any(Type &&type)
|
||||
: meta_any{std::in_place_type<std::remove_cv_t<std::remove_reference_t<Type>>>, std::forward<Type>(type)}
|
||||
meta_any(Type &&value)
|
||||
: meta_any{std::in_place_type<std::remove_cv_t<std::remove_reference_t<Type>>>, std::forward<Type>(value)}
|
||||
{}
|
||||
|
||||
/**
|
||||
@@ -455,12 +447,12 @@ public:
|
||||
/**
|
||||
* @brief Assignment operator.
|
||||
* @tparam Type Type of object to use to initialize the container.
|
||||
* @param type An instance of an object to use to initialize the container.
|
||||
* @param value An instance of an object to use to initialize the container.
|
||||
* @return This meta any object.
|
||||
*/
|
||||
template<typename Type>
|
||||
meta_any & operator=(Type &&type) {
|
||||
return (*this = meta_any{std::forward<Type>(type)});
|
||||
meta_any & operator=(Type &&value) {
|
||||
return (*this = meta_any{std::forward<Type>(value)});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -592,6 +584,14 @@ public:
|
||||
*this = meta_any{std::in_place_type_t<Type>{}, std::forward<Args>(args)...};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Indirection operator for aliasing construction.
|
||||
* @return An alias to the contained object.
|
||||
*/
|
||||
meta_any operator *() const ENTT_NOEXCEPT {
|
||||
return meta_any{node, instance};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns false if a container is empty, true otherwise.
|
||||
* @return False if the container is empty, true otherwise.
|
||||
@@ -649,62 +649,37 @@ private:
|
||||
* @brief Opaque pointers to instances of any type.
|
||||
*
|
||||
* A handle doesn't perform copies and isn't responsible for the contained
|
||||
* object. It doesn't prolong the lifetime of the pointed instance. Users are
|
||||
* responsible for ensuring that the target object remains alive for the entire
|
||||
* interval of use of the handle.
|
||||
* object. It doesn't prolong the lifetime of the pointed instance.<br/>
|
||||
* Handles are used mainly to gnerate aliases for actual objects when needed.
|
||||
*/
|
||||
class meta_handle {
|
||||
/*! @brief A meta any is allowed to _inherit_ from a meta handle. */
|
||||
friend class meta_any;
|
||||
|
||||
public:
|
||||
struct meta_handle {
|
||||
/*! @brief Default constructor. */
|
||||
meta_handle() ENTT_NOEXCEPT = default;
|
||||
meta_handle() = default;
|
||||
|
||||
/**
|
||||
* @brief Constructs a meta handle from a meta any object.
|
||||
* @param any A reference to an object to use to initialize the handle.
|
||||
* @brief Creates an alias for the actual object.
|
||||
* @tparam Type Type of object to use to initialize the container.
|
||||
* @param value An instance of an object to use to initialize the container.
|
||||
*/
|
||||
meta_handle(meta_any &any) ENTT_NOEXCEPT
|
||||
: node{any.node},
|
||||
instance{any.instance}
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Constructs a meta handle from a given instance.
|
||||
* @tparam Type Type of object to use to initialize the handle.
|
||||
* @param obj A reference to an object to use to initialize the handle.
|
||||
*/
|
||||
template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_handle>>>
|
||||
meta_handle(Type &obj) ENTT_NOEXCEPT
|
||||
: node{internal::meta_info<Type>::resolve()},
|
||||
instance{&obj}
|
||||
{}
|
||||
|
||||
/*! @copydoc meta_any::type */
|
||||
inline meta_type type() const ENTT_NOEXCEPT;
|
||||
|
||||
/*! @copydoc meta_any::data */
|
||||
const void * data() const ENTT_NOEXCEPT {
|
||||
return instance;
|
||||
template<typename Type>
|
||||
meta_handle(Type &&value) ENTT_NOEXCEPT
|
||||
: meta_handle{}
|
||||
{
|
||||
if constexpr(std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_any>) {
|
||||
any = *value;
|
||||
} else {
|
||||
static_assert(std::is_lvalue_reference_v<Type>);
|
||||
any = std::ref(value);
|
||||
}
|
||||
}
|
||||
|
||||
/*! @copydoc data */
|
||||
void * data() ENTT_NOEXCEPT {
|
||||
return const_cast<void *>(std::as_const(*this).data());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns false if a handle is empty, true otherwise.
|
||||
* @return False if the handle is empty, true otherwise.
|
||||
*/
|
||||
explicit operator bool() const ENTT_NOEXCEPT {
|
||||
return instance;
|
||||
/*! @copydoc meta_any::operator* */
|
||||
meta_any operator *() const {
|
||||
return any;
|
||||
}
|
||||
|
||||
private:
|
||||
const internal::meta_type_node *node;
|
||||
void *instance;
|
||||
meta_any any;
|
||||
};
|
||||
|
||||
|
||||
@@ -914,9 +889,13 @@ struct meta_ctor {
|
||||
* @return A meta any containing the new instance, if any.
|
||||
*/
|
||||
template<typename... Args>
|
||||
meta_any invoke(Args &&... args) const {
|
||||
std::array<meta_any, sizeof...(Args)> arguments{{std::forward<Args>(args)...}};
|
||||
return sizeof...(Args) == size() ? node->invoke(arguments.data()) : meta_any{};
|
||||
meta_any invoke([[maybe_unused]] Args &&... args) const {
|
||||
if constexpr(sizeof...(Args) == 0) {
|
||||
return sizeof...(Args) == size() ? node->invoke(nullptr) : meta_any{};
|
||||
} else {
|
||||
meta_any arguments[]{std::forward<Args>(args)...};
|
||||
return sizeof...(Args) == size() ? node->invoke(arguments) : meta_any{};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -965,54 +944,6 @@ inline bool operator!=(const meta_ctor &lhs, const meta_ctor &rhs) ENTT_NOEXCEPT
|
||||
}
|
||||
|
||||
|
||||
/*! @brief Opaque container for meta destructors. */
|
||||
struct meta_dtor {
|
||||
/*! @copydoc meta_prop::meta_prop */
|
||||
meta_dtor(const internal::meta_dtor_node *curr = nullptr) ENTT_NOEXCEPT
|
||||
: node{curr}
|
||||
{}
|
||||
|
||||
/*! @copydoc meta_base::parent */
|
||||
inline meta_type parent() const ENTT_NOEXCEPT;
|
||||
|
||||
/**
|
||||
* @brief Destroys an instance of the underlying type.
|
||||
*
|
||||
* It must be possible to cast the instance to the parent type of the meta
|
||||
* destructor. Otherwise, invoking the meta destructor results in an
|
||||
* undefined behavior.
|
||||
*
|
||||
* @param handle An opaque pointer to an instance of the underlying type.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
bool invoke(meta_handle handle) const {
|
||||
return node->invoke(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns true if a meta object is valid, false otherwise.
|
||||
* @return True if the meta object is valid, false otherwise.
|
||||
*/
|
||||
explicit operator bool() const ENTT_NOEXCEPT {
|
||||
return node;
|
||||
}
|
||||
|
||||
/*! @copydoc meta_prop::operator== */
|
||||
bool operator==(const meta_dtor &other) const ENTT_NOEXCEPT {
|
||||
return node == other.node;
|
||||
}
|
||||
|
||||
private:
|
||||
const internal::meta_dtor_node *node;
|
||||
};
|
||||
|
||||
|
||||
/*! @copydoc operator!=(const meta_prop &, const meta_prop &) */
|
||||
inline bool operator!=(const meta_dtor &lhs, const meta_dtor &rhs) ENTT_NOEXCEPT {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
|
||||
/*! @brief Opaque container for meta data. */
|
||||
struct meta_data {
|
||||
/*! @copydoc meta_prop::meta_prop */
|
||||
@@ -1057,13 +988,13 @@ struct meta_data {
|
||||
* of the variable is possible. Otherwise, invoking the setter does nothing.
|
||||
*
|
||||
* @tparam Type Type of value to assign.
|
||||
* @param handle An opaque pointer to an instance of the underlying type.
|
||||
* @param instance An opaque instance of the underlying type.
|
||||
* @param value Parameter to use to set the underlying variable.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
template<typename Type>
|
||||
bool set(meta_handle handle, Type &&value) const {
|
||||
return node->set(handle, meta_any{}, std::forward<Type>(value));
|
||||
bool set(meta_handle instance, Type &&value) const {
|
||||
return node->set(*instance, {}, std::forward<Type>(value));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1076,15 +1007,15 @@ struct meta_data {
|
||||
* type is possible. Otherwise, invoking the setter does nothing.
|
||||
*
|
||||
* @tparam Type Type of value to assign.
|
||||
* @param handle An opaque pointer to an instance of the underlying type.
|
||||
* @param instance An opaque instance of the underlying type.
|
||||
* @param index Position of the underlying element to set.
|
||||
* @param value Parameter to use to set the underlying element.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
template<typename Type>
|
||||
bool set(meta_handle handle, std::size_t index, Type &&value) const {
|
||||
bool set(meta_handle instance, std::size_t index, Type &&value) const {
|
||||
ENTT_ASSERT(index < node->type()->extent);
|
||||
return node->set(handle, index, std::forward<Type>(value));
|
||||
return node->set(*instance, index, std::forward<Type>(value));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1093,11 +1024,11 @@ struct meta_data {
|
||||
* It must be possible to cast the instance to the parent type of the meta
|
||||
* data. Otherwise, invoking the getter results in an undefined behavior.
|
||||
*
|
||||
* @param handle An opaque pointer to an instance of the underlying type.
|
||||
* @param instance An opaque instance of the underlying type.
|
||||
* @return A meta any containing the value of the underlying variable.
|
||||
*/
|
||||
meta_any get(meta_handle handle) const {
|
||||
return node->get(handle, meta_any{});
|
||||
meta_any get(meta_handle instance) const {
|
||||
return node->get(*instance, {});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1106,13 +1037,13 @@ struct meta_data {
|
||||
* It must be possible to cast the instance to the parent type of the meta
|
||||
* data. Otherwise, invoking the getter results in an undefined behavior.
|
||||
*
|
||||
* @param handle An opaque pointer to an instance of the underlying type.
|
||||
* @param instance An opaque instance of the underlying type.
|
||||
* @param index Position of the underlying element to get.
|
||||
* @return A meta any containing the value of the underlying element.
|
||||
*/
|
||||
meta_any get(meta_handle handle, std::size_t index) const {
|
||||
meta_any get(meta_handle instance, std::size_t index) const {
|
||||
ENTT_ASSERT(index < node->type()->extent);
|
||||
return node->get(handle, index);
|
||||
return node->get(*instance, index);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1227,15 +1158,14 @@ struct meta_func {
|
||||
* undefined behavior.
|
||||
*
|
||||
* @tparam Args Types of arguments to use to invoke the function.
|
||||
* @param handle An opaque pointer to an instance of the underlying type.
|
||||
* @param instance An opaque instance of the underlying type.
|
||||
* @param args Parameters to use to invoke the function.
|
||||
* @return A meta any containing the returned value, if any.
|
||||
*/
|
||||
template<typename... Args>
|
||||
meta_any invoke(meta_handle handle, Args &&... args) const {
|
||||
// makes aliasing on the values and passes forward references if any
|
||||
std::array<meta_any, sizeof...(Args)> arguments{{meta_handle{args}...}};
|
||||
return sizeof...(Args) == size() ? node->invoke(handle, arguments.data()) : meta_any{};
|
||||
meta_any invoke(meta_handle instance, Args &&... args) const {
|
||||
meta_any arguments[]{*instance, std::forward<Args>(args)...};
|
||||
return sizeof...(Args) == size() ? node->invoke(arguments[0], &arguments[sizeof...(Args) != 0]) : meta_any{};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1504,14 +1434,6 @@ public:
|
||||
return ctor<Args...>(std::index_sequence_for<Args...>{});
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the meta destructor associated with a given type.
|
||||
* @return The meta destructor associated with the given type, if any.
|
||||
*/
|
||||
meta_dtor dtor() const ENTT_NOEXCEPT {
|
||||
return node->dtor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterates all the meta data of a meta type.
|
||||
*
|
||||
@@ -1581,34 +1503,22 @@ public:
|
||||
*/
|
||||
template<typename... Args>
|
||||
meta_any construct(Args &&... args) const {
|
||||
std::array<meta_any, sizeof...(Args)> arguments{{std::forward<Args>(args)...}};
|
||||
meta_any any{};
|
||||
auto construct_if = [this](auto *params) {
|
||||
meta_any any{};
|
||||
|
||||
internal::find_if<&internal::meta_type_node::ctor>([data = arguments.data(), &any](const auto *curr) {
|
||||
if(curr->size == sizeof...(args)) {
|
||||
any = curr->invoke(data);
|
||||
}
|
||||
internal::find_if<&internal::meta_type_node::ctor>([params, &any](const auto *curr) {
|
||||
return (curr->size == sizeof...(args)) && (any = curr->invoke(params));
|
||||
}, node);
|
||||
|
||||
return static_cast<bool>(any);
|
||||
}, node);
|
||||
return any;
|
||||
};
|
||||
|
||||
return any;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destroys an instance of the underlying type.
|
||||
*
|
||||
* It must be possible to cast the instance to the underlying type.
|
||||
* Otherwise, invoking the meta destructor results in an undefined
|
||||
* behavior.<br/>
|
||||
* If no destructor has been set, this function returns true without doing
|
||||
* anything.
|
||||
*
|
||||
* @param handle An opaque pointer to an instance of the underlying type.
|
||||
* @return True in case of success, false otherwise.
|
||||
*/
|
||||
bool destroy(meta_handle handle) const {
|
||||
return (handle.type() == node) && (!node->dtor || node->dtor->invoke(handle));
|
||||
if constexpr(sizeof...(Args) == 0) {
|
||||
return construct_if(nullptr);
|
||||
} else {
|
||||
meta_any arguments[]{std::forward<Args>(args)...};
|
||||
return construct_if(arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1678,24 +1588,11 @@ inline bool operator!=(const meta_type &lhs, const meta_type &rhs) ENTT_NOEXCEPT
|
||||
}
|
||||
|
||||
|
||||
inline meta_any::meta_any(meta_handle handle) ENTT_NOEXCEPT
|
||||
: meta_any{}
|
||||
{
|
||||
node = handle.node;
|
||||
instance = handle.instance;
|
||||
}
|
||||
|
||||
|
||||
inline meta_type meta_any::type() const ENTT_NOEXCEPT {
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
inline meta_type meta_handle::type() const ENTT_NOEXCEPT {
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
inline meta_type meta_base::parent() const ENTT_NOEXCEPT {
|
||||
return node->parent;
|
||||
}
|
||||
@@ -1726,11 +1623,6 @@ inline meta_type meta_ctor::arg(size_type index) const ENTT_NOEXCEPT {
|
||||
}
|
||||
|
||||
|
||||
inline meta_type meta_dtor::parent() const ENTT_NOEXCEPT {
|
||||
return node->parent;
|
||||
}
|
||||
|
||||
|
||||
inline meta_type meta_data::parent() const ENTT_NOEXCEPT {
|
||||
return node->parent;
|
||||
}
|
||||
|
||||
@@ -289,22 +289,6 @@ TEST_F(Meta, Resolve) {
|
||||
ASSERT_TRUE(found);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaAnyFromMetaHandle) {
|
||||
int value = 42;
|
||||
entt::meta_handle handle{value};
|
||||
entt::meta_any any{handle};
|
||||
any.cast<int>() = 3;
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(any.try_cast<std::size_t>(), nullptr);
|
||||
ASSERT_EQ(any.try_cast<int>(), handle.data());
|
||||
ASSERT_EQ(std::as_const(any).try_cast<int>(), handle.data());
|
||||
ASSERT_EQ(any.data(), handle.data());
|
||||
ASSERT_EQ(std::as_const(any).data(), handle.data());
|
||||
ASSERT_EQ(value, 3);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaAnySBO) {
|
||||
entt::meta_any any{'c'};
|
||||
|
||||
@@ -901,35 +885,6 @@ TEST_F(Meta, MetaAnyConstConvert) {
|
||||
ASSERT_EQ(other.cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaHandleFromObject) {
|
||||
empty_type empty{};
|
||||
entt::meta_handle handle{empty};
|
||||
|
||||
ASSERT_TRUE(handle);
|
||||
ASSERT_EQ(handle.type(), entt::resolve<empty_type>());
|
||||
ASSERT_EQ(std::as_const(handle).data(), &empty);
|
||||
ASSERT_EQ(handle.data(), &empty);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaHandleFromMetaAny) {
|
||||
entt::meta_any any{42};
|
||||
entt::meta_handle handle{any};
|
||||
|
||||
ASSERT_TRUE(handle);
|
||||
ASSERT_EQ(handle.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(std::as_const(handle).data(), any.data());
|
||||
ASSERT_EQ(handle.data(), any.data());
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaHandleEmpty) {
|
||||
entt::meta_handle handle{};
|
||||
|
||||
ASSERT_FALSE(handle);
|
||||
ASSERT_FALSE(handle.type());
|
||||
ASSERT_EQ(std::as_const(handle).data(), nullptr);
|
||||
ASSERT_EQ(handle.data(), nullptr);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaProp) {
|
||||
auto prop = entt::resolve<char>().prop(props::prop_int);
|
||||
|
||||
@@ -1118,33 +1073,6 @@ TEST_F(Meta, MetaCtorFuncCastAndConvert) {
|
||||
ASSERT_EQ(any.cast<derived_type>().c, 'c');
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaDtor) {
|
||||
auto dtor = entt::resolve<empty_type>().dtor();
|
||||
empty_type empty{};
|
||||
|
||||
ASSERT_TRUE(dtor);
|
||||
ASSERT_NE(dtor, entt::meta_dtor{});
|
||||
ASSERT_EQ(dtor.parent(), entt::resolve("empty"_hs));
|
||||
ASSERT_EQ(empty_type::counter, 0);
|
||||
ASSERT_TRUE(dtor.invoke(empty));
|
||||
ASSERT_EQ(empty_type::counter, 1);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaDtorMetaAnyArg) {
|
||||
auto dtor = entt::resolve<empty_type>().dtor();
|
||||
entt::meta_any any{empty_type{}};
|
||||
|
||||
ASSERT_EQ(empty_type::counter, 0);
|
||||
ASSERT_TRUE(dtor.invoke(any));
|
||||
ASSERT_EQ(empty_type::counter, 1);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaDtorMetaAnyInvalidArg) {
|
||||
auto instance = 0;
|
||||
ASSERT_FALSE(entt::resolve<empty_type>().dtor().invoke(instance));
|
||||
}
|
||||
|
||||
|
||||
TEST_F(Meta, MetaData) {
|
||||
auto data = entt::resolve<data_type>().data("i"_hs);
|
||||
data_type instance{};
|
||||
@@ -1690,8 +1618,8 @@ TEST_F(Meta, MetaFuncByReference) {
|
||||
entt::meta_any any{3};
|
||||
int value = 4;
|
||||
|
||||
ASSERT_EQ(func.invoke({}, value).cast<int>(), 8);
|
||||
ASSERT_EQ(func.invoke({}, any).cast<int>(), 6);
|
||||
ASSERT_EQ(func.invoke({}, std::ref(value)).cast<int>(), 8);
|
||||
ASSERT_EQ(func.invoke({}, *any).cast<int>(), 6);
|
||||
ASSERT_EQ(any.cast<int>(), 6);
|
||||
ASSERT_EQ(value, 8);
|
||||
}
|
||||
@@ -1786,11 +1714,6 @@ TEST_F(Meta, MetaTypeCtor) {
|
||||
ASSERT_TRUE((type.ctor<const derived_type &, double>()));
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaTypeDtor) {
|
||||
ASSERT_TRUE(entt::resolve<fat_type>().dtor());
|
||||
ASSERT_FALSE(entt::resolve<int>().dtor());
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaTypeData) {
|
||||
auto type = entt::resolve<data_type>();
|
||||
int counter{};
|
||||
@@ -1857,52 +1780,6 @@ TEST_F(Meta, MetaTypeConstructCastAndConvert) {
|
||||
ASSERT_EQ(any.cast<derived_type>().c, 'c');
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaTypeDestroyDtor) {
|
||||
auto type = entt::resolve<empty_type>();
|
||||
empty_type instance;
|
||||
|
||||
ASSERT_EQ(empty_type::counter, 0);
|
||||
ASSERT_TRUE(type.destroy(instance));
|
||||
ASSERT_EQ(empty_type::counter, 1);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaTypeDestroyDtorInvalidArg) {
|
||||
auto type = entt::resolve<empty_type>();
|
||||
auto instance = 'c';
|
||||
|
||||
ASSERT_EQ(empty_type::counter, 0);
|
||||
ASSERT_FALSE(type.destroy(instance));
|
||||
ASSERT_EQ(empty_type::counter, 0);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaTypeDestroyDtorCastAndConvert) {
|
||||
auto type = entt::resolve<empty_type>();
|
||||
fat_type instance{};
|
||||
|
||||
ASSERT_EQ(empty_type::counter, 0);
|
||||
ASSERT_FALSE(type.destroy(instance));
|
||||
ASSERT_EQ(empty_type::counter, 0);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaTypeDestroyNoDtor) {
|
||||
auto instance = 'c';
|
||||
ASSERT_TRUE(entt::resolve<char>().destroy(instance));
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaTypeDestroyNoDtorInvalidArg) {
|
||||
auto instance = 42;
|
||||
ASSERT_FALSE(entt::resolve<char>().destroy(instance));
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaTypeDestroyNoDtorVoid) {
|
||||
ASSERT_FALSE(entt::resolve<void>().destroy({}));
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaTypeDestroyNoDtorCastAndConvert) {
|
||||
auto instance = 42.;
|
||||
ASSERT_FALSE(entt::resolve<int>().destroy(instance));
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaDataFromBase) {
|
||||
auto type = entt::resolve<concrete_type>();
|
||||
concrete_type instance;
|
||||
|
||||
Reference in New Issue
Block a user