meta:
* meta_prop_node is no longer static * we can attach multiple properties at different times * meta property keys are of type id_type only * removed meta_factory::props (use prop instead) * meta range returns id and meta object pairs now * removed mera_prop::key (id returned by meta ranges)
This commit is contained in:
@@ -26,18 +26,6 @@ namespace entt {
|
||||
|
||||
namespace internal {
|
||||
|
||||
inline void link_prop_if_required(internal::meta_prop_node **ref, internal::meta_prop_node &node) noexcept {
|
||||
for(auto it = *ref; it; it = it->next) {
|
||||
if(it == &node) {
|
||||
return;
|
||||
}
|
||||
ENTT_ASSERT(it->id != node.id, "Duplicate identifier");
|
||||
}
|
||||
|
||||
node.next = *ref;
|
||||
*ref = &node;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -82,95 +70,39 @@ class meta_factory;
|
||||
/**
|
||||
* @brief Extended meta factory to be used for reflection purposes.
|
||||
* @tparam Type Reflected type for which the factory was created.
|
||||
* @tparam Spec Property specialization pack used to disambiguate overloads.
|
||||
* @tparam Prop Type of container to store properties.
|
||||
*/
|
||||
template<typename Type, typename... Spec>
|
||||
class meta_factory<Type, Spec...>: public meta_factory<Type> {
|
||||
template<std::size_t Step = 0, typename... Property, typename... Other>
|
||||
void unroll(choice_t<2>, std::tuple<Property...> property, Other &&...other) noexcept {
|
||||
std::apply([this](auto &&...curr) { (this->unroll<Step>(choice<2>, std::forward<Property>(curr)...)); }, property);
|
||||
unroll<Step + sizeof...(Property)>(choice<2>, std::forward<Other>(other)...);
|
||||
}
|
||||
|
||||
template<std::size_t Step = 0, typename... Property, typename... Other>
|
||||
void unroll(choice_t<1>, std::pair<Property...> property, Other &&...other) noexcept {
|
||||
assign<Step>(std::move(property.first), std::move(property.second));
|
||||
unroll<Step + 1>(choice<2>, std::forward<Other>(other)...);
|
||||
}
|
||||
|
||||
template<std::size_t Step = 0, typename Property, typename... Other>
|
||||
void unroll(choice_t<0>, Property &&property, Other &&...other) noexcept {
|
||||
assign<Step>(std::forward<Property>(property));
|
||||
unroll<Step + 1>(choice<2>, std::forward<Other>(other)...);
|
||||
}
|
||||
|
||||
template<std::size_t>
|
||||
void unroll(choice_t<0>) noexcept {}
|
||||
|
||||
template<std::size_t = 0>
|
||||
void assign(meta_any key, meta_any value = {}) {
|
||||
static meta_any property[2u]{};
|
||||
|
||||
static internal::meta_prop_node node{
|
||||
nullptr,
|
||||
property[0u],
|
||||
property[1u]
|
||||
// tricks clang-format
|
||||
};
|
||||
|
||||
property[0u] = std::move(key);
|
||||
property[1u] = std::move(value);
|
||||
|
||||
internal::link_prop_if_required(ref, node);
|
||||
}
|
||||
|
||||
template<typename Type, typename Prop>
|
||||
class meta_factory<Type, Prop>: public meta_factory<Type> {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs an extended factory from a given node.
|
||||
* @param target The underlying node to which to assign the properties.
|
||||
* @param target The underlying container to store properties.
|
||||
*/
|
||||
meta_factory(internal::meta_prop_node **target) noexcept
|
||||
: ref{target} {}
|
||||
meta_factory(Prop &target) noexcept
|
||||
: container{&target} {}
|
||||
|
||||
/**
|
||||
* @brief Assigns a property to the last meta object created.
|
||||
*
|
||||
* Both the key and the value (if any) must be at least copy constructible.
|
||||
*
|
||||
* @tparam PropertyOrKey Type of the property or property key.
|
||||
* @tparam Value Optional type of the property value.
|
||||
* @param property_or_key Property or property key.
|
||||
* @param key Property key.
|
||||
* @param value Optional property value.
|
||||
* @return A meta factory for the parent type.
|
||||
* @return An extended meta factory for the given type.
|
||||
*/
|
||||
template<typename PropertyOrKey, typename... Value>
|
||||
meta_factory<Type> prop(PropertyOrKey &&property_or_key, Value &&...value) {
|
||||
if constexpr(sizeof...(Value) == 0) {
|
||||
unroll(choice<2>, std::forward<PropertyOrKey>(property_or_key));
|
||||
} else {
|
||||
assign(std::forward<PropertyOrKey>(property_or_key), std::forward<Value>(value)...);
|
||||
}
|
||||
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()...,
|
||||
std::forward<Value>(value)...};
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns properties to the last meta object created.
|
||||
*
|
||||
* Both key and value (if any) must be at least copy constructible.
|
||||
*
|
||||
* @tparam Property Types of the properties.
|
||||
* @param property Properties to assign to the last meta object created.
|
||||
* @return A meta factory for the parent type.
|
||||
*/
|
||||
template<typename... Property>
|
||||
meta_factory<Type> props(Property... property) {
|
||||
unroll(choice<2>, std::forward<Property>(property)...);
|
||||
return {};
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
internal::meta_prop_node **ref;
|
||||
Prop *container;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -188,14 +120,13 @@ class meta_factory<Type> {
|
||||
owner->data[id] = internal::meta_data_node{
|
||||
/* 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,
|
||||
nullptr,
|
||||
Setter::size,
|
||||
internal::meta_node<std::remove_cv_t<std::remove_reference_t<data_type>>>::resolve(),
|
||||
&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_getter<Type, Getter, Policy>};
|
||||
|
||||
return meta_factory<Type, Setter, std::integral_constant<decltype(Getter), Getter>>{&owner->data[id].prop};
|
||||
return meta_factory<Type, decltype(internal::meta_data_node::prop)>{owner->data[id].prop};
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -210,7 +141,7 @@ public:
|
||||
*/
|
||||
auto type(const id_type id = type_hash<Type>::value()) noexcept {
|
||||
internal::link_type_if_required(owner, id);
|
||||
return meta_factory<Type, Type>{&owner->prop};
|
||||
return meta_factory<Type, decltype(internal::meta_type_node::prop)>{owner->prop};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,27 +309,25 @@ public:
|
||||
owner->data[id] = internal::meta_data_node{
|
||||
/* this is never static */
|
||||
std::is_const_v<data_type> ? internal::meta_traits::is_const : internal::meta_traits::is_none,
|
||||
nullptr,
|
||||
1u,
|
||||
internal::meta_node<std::remove_const_t<data_type>>::resolve(),
|
||||
&meta_arg<type_list<std::remove_const_t<data_type>>>,
|
||||
&meta_setter<Type, Data>,
|
||||
&meta_getter<Type, Data, Policy>};
|
||||
|
||||
return meta_factory<Type, std::integral_constant<decltype(Data), Data>, std::integral_constant<decltype(Data), Data>>{&owner->data[id].prop};
|
||||
return meta_factory<Type, decltype(internal::meta_data_node::prop)>{owner->data[id].prop};
|
||||
} else {
|
||||
using data_type = std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>;
|
||||
|
||||
owner->data[id] = internal::meta_data_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,
|
||||
nullptr,
|
||||
1u,
|
||||
internal::meta_node<std::remove_const_t<data_type>>::resolve(),
|
||||
&meta_arg<type_list<std::remove_const_t<data_type>>>,
|
||||
&meta_setter<Type, Data>,
|
||||
&meta_getter<Type, Data, Policy>};
|
||||
|
||||
return meta_factory<Type, std::integral_constant<decltype(Data), Data>>{&owner->data[id].prop};
|
||||
return meta_factory<Type, decltype(internal::meta_data_node::prop)>{owner->data[id].prop};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,28 +360,26 @@ public:
|
||||
owner->data[id] = internal::meta_data_node{
|
||||
/* this is never static */
|
||||
internal::meta_traits::is_const,
|
||||
nullptr,
|
||||
0u,
|
||||
internal::meta_node<std::remove_cv_t<std::remove_reference_t<data_type>>>::resolve(),
|
||||
&meta_arg<type_list<>>,
|
||||
&meta_setter<Type, Setter>,
|
||||
&meta_getter<Type, Getter, Policy>};
|
||||
|
||||
return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&owner->data[id].prop};
|
||||
return meta_factory<Type, decltype(internal::meta_data_node::prop)>{owner->data[id].prop};
|
||||
} else {
|
||||
using args_type = typename meta_function_helper_t<Type, decltype(Setter)>::args_type;
|
||||
|
||||
owner->data[id] = internal::meta_data_node{
|
||||
/* this is never static nor const */
|
||||
internal::meta_traits::is_none,
|
||||
nullptr,
|
||||
1u,
|
||||
internal::meta_node<std::remove_cv_t<std::remove_reference_t<data_type>>>::resolve(),
|
||||
&meta_arg<type_list<type_list_element_t<args_type::size != 1u, args_type>>>,
|
||||
&meta_setter<Type, Setter>,
|
||||
&meta_getter<Type, Getter, Policy>};
|
||||
|
||||
return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&owner->data[id].prop};
|
||||
return meta_factory<Type, decltype(internal::meta_data_node::prop)>{owner->data[id].prop};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,7 +427,6 @@ public:
|
||||
{},
|
||||
(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),
|
||||
nullptr,
|
||||
nullptr,
|
||||
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(),
|
||||
&meta_arg<typename descriptor::args_type>,
|
||||
@@ -509,7 +435,7 @@ public:
|
||||
};
|
||||
|
||||
internal::link_func_if_required(owner, id, node);
|
||||
return meta_factory<Type, std::integral_constant<decltype(Candidate), Candidate>>{&node.prop};
|
||||
return meta_factory<Type, decltype(internal::meta_func_node::prop)>{node.prop};
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -531,7 +457,7 @@ template<typename Type>
|
||||
[[nodiscard]] auto meta() noexcept {
|
||||
auto *const node = internal::meta_node<Type>::resolve();
|
||||
// extended meta factory to allow assigning properties to opaque meta types
|
||||
return meta_factory<Type, Type>{&node->prop};
|
||||
return meta_factory<Type, decltype(internal::meta_type_node::prop)>{node->prop};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -546,26 +472,20 @@ template<typename Type>
|
||||
* @param id Unique identifier.
|
||||
*/
|
||||
inline void meta_reset(const id_type id) noexcept {
|
||||
auto clear_chain = [](auto **curr, auto... member) {
|
||||
for(; *curr; *curr = std::exchange((*curr)->next, nullptr)) {
|
||||
if constexpr(sizeof...(member) != 0u) {
|
||||
static_assert(sizeof...(member) == 1u, "Assert in defense of the future me");
|
||||
for(auto **sub = (&((*curr)->*member), ...); *sub; *sub = std::exchange((*sub)->next, nullptr)) {}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for(auto **it = internal::meta_context::global(); *it; it = &(*it)->next) {
|
||||
if(auto *node = *it; node->id == id) {
|
||||
clear_chain(&node->prop);
|
||||
clear_chain(&node->func, &internal::meta_func_node::prop);
|
||||
for(auto **curr = &node->func; *curr; *curr = std::exchange((*curr)->next, nullptr)) {
|
||||
(*curr)->prop.clear();
|
||||
}
|
||||
|
||||
node->id = {};
|
||||
node->prop.clear();
|
||||
node->ctor.clear();
|
||||
node->base.clear();
|
||||
node->conv.clear();
|
||||
node->data.clear();
|
||||
node->dtor.dtor = nullptr;
|
||||
|
||||
*it = std::exchange(node->next, nullptr);
|
||||
|
||||
break;
|
||||
|
||||
@@ -664,20 +664,12 @@ struct meta_prop {
|
||||
meta_prop(const node_type *curr = nullptr) noexcept
|
||||
: node{curr} {}
|
||||
|
||||
/**
|
||||
* @brief Returns the stored key as a const reference.
|
||||
* @return A wrapper containing the key stored with the property.
|
||||
*/
|
||||
[[nodiscard]] meta_any key() const {
|
||||
return node->id.as_ref();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the stored value by copy.
|
||||
* @return A wrapper containing the value stored with the property.
|
||||
*/
|
||||
[[nodiscard]] meta_any value() const {
|
||||
return node->value;
|
||||
return (node && node->type) ? node->type->from_void(nullptr, node->value.data()) : meta_any{};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -772,8 +764,8 @@ struct meta_data {
|
||||
* @brief Returns a range to visit registered meta properties.
|
||||
* @return An iterable range to visit registered meta properties.
|
||||
*/
|
||||
[[nodiscard]] old_meta_range<meta_prop> prop() const noexcept {
|
||||
return {node->prop, nullptr};
|
||||
[[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_data_node::prop)::const_iterator> prop() const noexcept {
|
||||
return {node->prop.cbegin(), node->prop.cend()};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -781,11 +773,9 @@ struct meta_data {
|
||||
* @param key The key to use to search for a property.
|
||||
* @return The registered meta property for the given key, if any.
|
||||
*/
|
||||
[[nodiscard]] meta_prop prop(meta_any key) const {
|
||||
for(auto curr: prop()) {
|
||||
if(curr.key() == key) {
|
||||
return curr;
|
||||
}
|
||||
[[nodiscard]] meta_prop prop(const id_type key) const {
|
||||
if(auto it = node->prop.find(key); it != node->prop.cend()) {
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -891,8 +881,8 @@ struct meta_func {
|
||||
}
|
||||
|
||||
/*! @copydoc meta_data::prop */
|
||||
[[nodiscard]] old_meta_range<meta_prop> prop() const noexcept {
|
||||
return {node->prop, nullptr};
|
||||
[[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_func_node::prop)::const_iterator> prop() const noexcept {
|
||||
return {node->prop.cbegin(), node->prop.cend()};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -900,11 +890,9 @@ struct meta_func {
|
||||
* @param key The key to use to search for a property.
|
||||
* @return The registered meta property for the given key, if any.
|
||||
*/
|
||||
[[nodiscard]] meta_prop prop(meta_any key) const {
|
||||
for(auto curr: prop()) {
|
||||
if(curr.key() == key) {
|
||||
return curr;
|
||||
}
|
||||
[[nodiscard]] meta_prop prop(const id_type key) const {
|
||||
if(auto it = node->prop.find(key); it != node->prop.cend()) {
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
@@ -1364,8 +1352,8 @@ public:
|
||||
* @brief Returns a range to visit registered top-level meta properties.
|
||||
* @return An iterable range to visit registered top-level meta properties.
|
||||
*/
|
||||
[[nodiscard]] old_meta_range<meta_prop> prop() const noexcept {
|
||||
return {node->prop, nullptr};
|
||||
[[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_type_node::prop)::const_iterator> prop() const noexcept {
|
||||
return {node->prop.cbegin(), node->prop.cend()};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1376,8 +1364,18 @@ public:
|
||||
* @param key The key to use to search for a property.
|
||||
* @return The registered meta property for the given key, if any.
|
||||
*/
|
||||
[[nodiscard]] meta_prop prop(meta_any key) const {
|
||||
return internal::find_by<&internal::meta_type_node::prop>(key, node);
|
||||
[[nodiscard]] meta_prop prop(const id_type key) const {
|
||||
if(auto it = node->prop.find(key); it != node->prop.cend()) {
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
for(auto &&curr: base()) {
|
||||
if(auto elem = curr.second.prop(key); elem) {
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,9 +46,8 @@ enum class meta_traits : std::uint32_t {
|
||||
struct meta_type_node;
|
||||
|
||||
struct meta_prop_node {
|
||||
meta_prop_node *next;
|
||||
const meta_any &id;
|
||||
meta_any &value;
|
||||
meta_type_node *type{nullptr};
|
||||
basic_any<0u> value{};
|
||||
};
|
||||
|
||||
struct meta_base_node {
|
||||
@@ -76,12 +75,12 @@ struct meta_data_node {
|
||||
using size_type = std::size_t;
|
||||
|
||||
meta_traits traits;
|
||||
meta_prop_node *prop;
|
||||
size_type arity;
|
||||
meta_type_node *type;
|
||||
meta_type (*arg)(const size_type) noexcept;
|
||||
bool (*set)(meta_handle, meta_any);
|
||||
meta_any (*get)(meta_handle);
|
||||
dense_map<id_type, meta_prop_node, identity> prop{};
|
||||
};
|
||||
|
||||
struct meta_func_node {
|
||||
@@ -90,11 +89,11 @@ struct meta_func_node {
|
||||
id_type id;
|
||||
const meta_traits traits;
|
||||
meta_func_node *next;
|
||||
meta_prop_node *prop;
|
||||
const size_type arity;
|
||||
meta_type_node *const ret;
|
||||
meta_type (*const arg)(const size_type) noexcept;
|
||||
meta_any (*const invoke)(meta_handle, meta_any *const);
|
||||
dense_map<id_type, meta_prop_node, identity> prop{};
|
||||
};
|
||||
|
||||
struct meta_template_node {
|
||||
@@ -112,13 +111,13 @@ struct meta_type_node {
|
||||
id_type id;
|
||||
const meta_traits traits;
|
||||
meta_type_node *next;
|
||||
meta_prop_node *prop;
|
||||
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_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{};
|
||||
@@ -132,7 +131,7 @@ meta_type_node *meta_arg_node(type_list<Args...>, const std::size_t index) noexc
|
||||
|
||||
template<typename Type>
|
||||
class ENTT_API meta_node {
|
||||
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Invalid type");
|
||||
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>) {
|
||||
@@ -195,7 +194,6 @@ public:
|
||||
| (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,
|
||||
nullptr,
|
||||
size_of_v<Type>,
|
||||
&meta_node<std::remove_cv_t<std::remove_pointer_t<Type>>>::resolve,
|
||||
meta_default_constructor(),
|
||||
|
||||
@@ -93,7 +93,7 @@ struct array_t {
|
||||
int local[5];
|
||||
};
|
||||
|
||||
enum class property_t {
|
||||
enum class property_t : entt::id_type {
|
||||
random,
|
||||
value
|
||||
};
|
||||
@@ -119,14 +119,14 @@ struct MetaData: ::testing::Test {
|
||||
entt::meta<clazz_t>()
|
||||
.type("clazz"_hs)
|
||||
.data<&clazz_t::i, entt::as_ref_t>("i"_hs)
|
||||
.prop(3, 0)
|
||||
.prop(3u, 0)
|
||||
.data<&clazz_t::i, entt::as_cref_t>("ci"_hs)
|
||||
.data<&clazz_t::j>("j"_hs)
|
||||
.prop(true, 1)
|
||||
.prop("true"_hs, 1)
|
||||
.data<&clazz_t::h>("h"_hs)
|
||||
.prop(property_t::random, 2)
|
||||
.prop(static_cast<entt::id_type>(property_t::random), 2)
|
||||
.data<&clazz_t::k>("k"_hs)
|
||||
.prop(property_t::value, 3)
|
||||
.prop(static_cast<entt::id_type>(property_t::value), 3)
|
||||
.data<&clazz_t::base>("base"_hs)
|
||||
.data<&clazz_t::i, entt::as_void_t>("void"_hs)
|
||||
.conv<int>();
|
||||
@@ -176,17 +176,16 @@ TEST_F(MetaData, Functionalities) {
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 42);
|
||||
|
||||
for(auto curr: data.prop()) {
|
||||
ASSERT_EQ(curr.key(), 3);
|
||||
ASSERT_EQ(curr.value(), 0);
|
||||
ASSERT_EQ(curr.first, 3u);
|
||||
ASSERT_EQ(curr.second.value(), 0);
|
||||
}
|
||||
|
||||
ASSERT_FALSE(data.prop(2));
|
||||
ASSERT_FALSE(data.prop('c'));
|
||||
|
||||
auto prop = data.prop(3);
|
||||
auto prop = data.prop(3u);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.key(), 3);
|
||||
ASSERT_EQ(prop.value(), 0);
|
||||
}
|
||||
|
||||
@@ -207,17 +206,16 @@ TEST_F(MetaData, Const) {
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 1);
|
||||
|
||||
for(auto curr: data.prop()) {
|
||||
ASSERT_EQ(curr.key(), true);
|
||||
ASSERT_EQ(curr.value(), 1);
|
||||
ASSERT_EQ(curr.first, "true"_hs);
|
||||
ASSERT_EQ(curr.second.value(), 1);
|
||||
}
|
||||
|
||||
ASSERT_FALSE(data.prop(false));
|
||||
ASSERT_FALSE(data.prop('c'));
|
||||
|
||||
auto prop = data.prop(true);
|
||||
auto prop = data.prop("true"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.key(), true);
|
||||
ASSERT_EQ(prop.value(), 1);
|
||||
}
|
||||
|
||||
@@ -237,17 +235,16 @@ TEST_F(MetaData, Static) {
|
||||
ASSERT_EQ(data.get({}).cast<int>(), 42);
|
||||
|
||||
for(auto curr: data.prop()) {
|
||||
ASSERT_EQ(curr.key(), property_t::random);
|
||||
ASSERT_EQ(curr.value(), 2);
|
||||
ASSERT_EQ(curr.first, static_cast<entt::id_type>(property_t::random));
|
||||
ASSERT_EQ(curr.second.value(), 2);
|
||||
}
|
||||
|
||||
ASSERT_FALSE(data.prop(property_t::value));
|
||||
ASSERT_FALSE(data.prop(static_cast<entt::id_type>(property_t::value)));
|
||||
ASSERT_FALSE(data.prop('c'));
|
||||
|
||||
auto prop = data.prop(property_t::random);
|
||||
auto prop = data.prop(static_cast<entt::id_type>(property_t::random));
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.key(), property_t::random);
|
||||
ASSERT_EQ(prop.value(), 2);
|
||||
}
|
||||
|
||||
@@ -267,17 +264,16 @@ TEST_F(MetaData, ConstStatic) {
|
||||
ASSERT_EQ(data.get({}).cast<int>(), 3);
|
||||
|
||||
for(auto curr: data.prop()) {
|
||||
ASSERT_EQ(curr.key(), property_t::value);
|
||||
ASSERT_EQ(curr.value(), 3);
|
||||
ASSERT_EQ(curr.first, static_cast<entt::id_type>(property_t::value));
|
||||
ASSERT_EQ(curr.second.value(), 3);
|
||||
}
|
||||
|
||||
ASSERT_FALSE(data.prop(property_t::random));
|
||||
ASSERT_FALSE(data.prop(static_cast<entt::id_type>(property_t::random)));
|
||||
ASSERT_FALSE(data.prop('c'));
|
||||
|
||||
auto prop = data.prop(property_t::value);
|
||||
auto prop = data.prop(static_cast<entt::id_type>(property_t::value));
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.key(), property_t::value);
|
||||
ASSERT_EQ(prop.value(), 3);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,15 +114,15 @@ struct MetaFunc: ::testing::Test {
|
||||
.func<&entt::registry::emplace_or_replace<func_t>>("emplace"_hs)
|
||||
.func<entt::overload<int(const base_t &, int, int)>(&func_t::f)>("f3"_hs)
|
||||
.func<entt::overload<int(int, int)>(&func_t::f)>("f2"_hs)
|
||||
.prop(true, false)
|
||||
.prop("true"_hs, false)
|
||||
.func<entt::overload<int(int) const>(&func_t::f)>("f1"_hs)
|
||||
.prop(true, false)
|
||||
.prop("true"_hs, false)
|
||||
.func<&func_t::g>("g"_hs)
|
||||
.prop(true, false)
|
||||
.prop("true"_hs, false)
|
||||
.func<func_t::h>("h"_hs)
|
||||
.prop(true, false)
|
||||
.prop("true"_hs, false)
|
||||
.func<func_t::k>("k"_hs)
|
||||
.prop(true, false)
|
||||
.prop("true"_hs, false)
|
||||
.func<&func_t::v, entt::as_void_t>("v"_hs)
|
||||
.func<&func_t::a, entt::as_ref_t>("a"_hs)
|
||||
.func<&func_t::a, entt::as_cref_t>("ca"_hs)
|
||||
@@ -180,17 +180,16 @@ TEST_F(MetaFunc, Functionalities) {
|
||||
ASSERT_EQ(func_t::value, 3);
|
||||
|
||||
for(auto curr: func.prop()) {
|
||||
ASSERT_EQ(curr.key(), true);
|
||||
ASSERT_FALSE(curr.value().template cast<bool>());
|
||||
ASSERT_EQ(curr.first, "true"_hs);
|
||||
ASSERT_FALSE(curr.second.value().template cast<bool>());
|
||||
}
|
||||
|
||||
ASSERT_FALSE(func.prop(false));
|
||||
ASSERT_FALSE(func.prop('c'));
|
||||
|
||||
auto prop = func.prop(true);
|
||||
auto prop = func.prop("true"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.key(), true);
|
||||
ASSERT_FALSE(prop.value().cast<bool>());
|
||||
}
|
||||
|
||||
@@ -218,17 +217,16 @@ TEST_F(MetaFunc, Const) {
|
||||
ASSERT_EQ(any.cast<int>(), 16);
|
||||
|
||||
for(auto curr: func.prop()) {
|
||||
ASSERT_EQ(curr.key(), true);
|
||||
ASSERT_FALSE(curr.value().template cast<bool>());
|
||||
ASSERT_EQ(curr.first, "true"_hs);
|
||||
ASSERT_FALSE(curr.second.value().template cast<bool>());
|
||||
}
|
||||
|
||||
ASSERT_FALSE(func.prop(false));
|
||||
ASSERT_FALSE(func.prop('c'));
|
||||
|
||||
auto prop = func.prop(true);
|
||||
auto prop = func.prop("true"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.key(), true);
|
||||
ASSERT_FALSE(prop.value().cast<bool>());
|
||||
}
|
||||
|
||||
@@ -254,17 +252,16 @@ TEST_F(MetaFunc, RetVoid) {
|
||||
ASSERT_EQ(func_t::value, 25);
|
||||
|
||||
for(auto curr: func.prop()) {
|
||||
ASSERT_EQ(curr.key(), true);
|
||||
ASSERT_FALSE(curr.value().template cast<bool>());
|
||||
ASSERT_EQ(curr.first, "true"_hs);
|
||||
ASSERT_FALSE(curr.second.value().template cast<bool>());
|
||||
}
|
||||
|
||||
ASSERT_FALSE(func.prop(false));
|
||||
ASSERT_FALSE(func.prop('c'));
|
||||
|
||||
auto prop = func.prop(true);
|
||||
auto prop = func.prop("true"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.key(), true);
|
||||
ASSERT_FALSE(prop.value().cast<bool>());
|
||||
}
|
||||
|
||||
@@ -292,17 +289,16 @@ TEST_F(MetaFunc, Static) {
|
||||
ASSERT_EQ(any.cast<int>(), 6);
|
||||
|
||||
for(auto curr: func.prop()) {
|
||||
ASSERT_EQ(curr.key(), true);
|
||||
ASSERT_FALSE(curr.value().template cast<bool>());
|
||||
ASSERT_EQ(curr.first, "true"_hs);
|
||||
ASSERT_FALSE(curr.second.value().template cast<bool>());
|
||||
}
|
||||
|
||||
ASSERT_FALSE(func.prop(false));
|
||||
ASSERT_FALSE(func.prop('c'));
|
||||
|
||||
auto prop = func.prop(true);
|
||||
auto prop = func.prop("true"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.key(), true);
|
||||
ASSERT_FALSE(prop.value().cast<bool>());
|
||||
}
|
||||
|
||||
@@ -327,18 +323,16 @@ TEST_F(MetaFunc, StaticRetVoid) {
|
||||
ASSERT_EQ(func_t::value, 42);
|
||||
|
||||
for(auto curr: func.prop()) {
|
||||
ASSERT_TRUE(curr);
|
||||
ASSERT_EQ(curr.key(), true);
|
||||
ASSERT_FALSE(curr.value().template cast<bool>());
|
||||
ASSERT_EQ(curr.first, "true"_hs);
|
||||
ASSERT_FALSE(curr.second.value().template cast<bool>());
|
||||
}
|
||||
|
||||
ASSERT_FALSE(func.prop(false));
|
||||
ASSERT_FALSE(func.prop('c'));
|
||||
|
||||
auto prop = func.prop(true);
|
||||
auto prop = func.prop("true"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.key(), true);
|
||||
ASSERT_FALSE(prop.value().cast<bool>());
|
||||
}
|
||||
|
||||
|
||||
@@ -22,11 +22,13 @@ struct MetaProp: ::testing::Test {
|
||||
|
||||
entt::meta<base_2_t>()
|
||||
.type("base_2"_hs)
|
||||
.props(std::make_pair("bool"_hs, false), std::make_pair("char[]"_hs, "char[]"));
|
||||
.prop("bool"_hs, false)
|
||||
.prop("char[]"_hs, "char[]");
|
||||
|
||||
entt::meta<base_3_t>()
|
||||
.type("base_3"_hs)
|
||||
.prop(std::make_tuple("key_only"_hs, std::make_pair("key"_hs, 42)));
|
||||
.prop("key_only"_hs)
|
||||
.prop("key"_hs, 42);
|
||||
|
||||
entt::meta<derived_t>()
|
||||
.type("derived"_hs)
|
||||
@@ -46,7 +48,6 @@ TEST_F(MetaProp, Functionalities) {
|
||||
auto prop = entt::resolve<base_1_t>().prop("int"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.key(), "int"_hs);
|
||||
ASSERT_EQ(prop.value(), 42);
|
||||
}
|
||||
|
||||
@@ -76,7 +77,6 @@ TEST_F(MetaProp, DeducedArrayType) {
|
||||
auto prop = entt::resolve<base_2_t>().prop("char[]"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.key(), "char[]"_hs);
|
||||
ASSERT_EQ(prop.value().type(), entt::resolve<const char *>());
|
||||
ASSERT_EQ(strcmp(prop.value().cast<const char *>(), "char[]"), 0);
|
||||
}
|
||||
@@ -89,18 +89,20 @@ TEST_F(MetaProp, ReRegistration) {
|
||||
auto *node = entt::internal::meta_node<base_1_t>::resolve();
|
||||
auto type = entt::resolve<base_1_t>();
|
||||
|
||||
ASSERT_NE(node->prop, nullptr);
|
||||
ASSERT_EQ(node->prop->next, nullptr);
|
||||
ASSERT_FALSE(node->prop.empty());
|
||||
ASSERT_EQ(node->prop.size(), 1u);
|
||||
|
||||
ASSERT_TRUE(type.prop("int"_hs));
|
||||
ASSERT_EQ(type.prop("int"_hs).value().cast<int>(), 42);
|
||||
|
||||
entt::meta<base_1_t>().prop("int"_hs, 0);
|
||||
entt::meta<base_1_t>().prop("double"_hs, 3.);
|
||||
|
||||
ASSERT_NE(node->prop, nullptr);
|
||||
ASSERT_EQ(node->prop->next, nullptr);
|
||||
ASSERT_FALSE(node->prop.empty());
|
||||
ASSERT_EQ(node->prop.size(), 2u);
|
||||
|
||||
ASSERT_FALSE(type.prop("int"_hs));
|
||||
ASSERT_TRUE(type.prop("int"_hs));
|
||||
ASSERT_TRUE(type.prop("double"_hs));
|
||||
ASSERT_EQ(type.prop("int"_hs).value().cast<int>(), 0);
|
||||
ASSERT_EQ(type.prop("double"_hs).value().cast<double>(), 3.);
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ struct overloaded_func_t {
|
||||
inline static int value = 0;
|
||||
};
|
||||
|
||||
enum class property_t {
|
||||
enum class property_t : entt::id_type {
|
||||
random,
|
||||
value,
|
||||
key_only,
|
||||
@@ -150,18 +150,24 @@ struct MetaType: ::testing::Test {
|
||||
entt::meta<property_t>()
|
||||
.type("property"_hs)
|
||||
.data<property_t::random>("random"_hs)
|
||||
.props(std::make_pair(property_t::random, 0), std::make_pair(property_t::value, 3))
|
||||
.prop(static_cast<entt::id_type>(property_t::random), 0)
|
||||
.prop(static_cast<entt::id_type>(property_t::value), 3)
|
||||
.data<property_t::value>("value"_hs)
|
||||
.props(std::make_pair(property_t::random, true), std::make_pair(property_t::value, 0), property_t::key_only, property_t::list)
|
||||
.prop(static_cast<entt::id_type>(property_t::random), true)
|
||||
.prop(static_cast<entt::id_type>(property_t::value), 0)
|
||||
.prop(static_cast<entt::id_type>(property_t::key_only))
|
||||
.prop(static_cast<entt::id_type>(property_t::list))
|
||||
.data<property_t::key_only>("key_only"_hs)
|
||||
.prop(property_t::key_only)
|
||||
.prop(static_cast<entt::id_type>(property_t::key_only))
|
||||
.data<property_t::list>("list"_hs)
|
||||
.props(std::make_pair(property_t::random, false), std::make_pair(property_t::value, 0), property_t::key_only)
|
||||
.prop(static_cast<entt::id_type>(property_t::random), false)
|
||||
.prop(static_cast<entt::id_type>(property_t::value), 0)
|
||||
.prop(static_cast<entt::id_type>(property_t::key_only))
|
||||
.data<set<property_t>, get<property_t>>("var"_hs);
|
||||
|
||||
entt::meta<clazz_t>()
|
||||
.type("clazz"_hs)
|
||||
.prop(property_t::value, 42)
|
||||
.prop(static_cast<entt::id_type>(property_t::value), 42)
|
||||
.ctor<const base_t &, int>()
|
||||
.data<&clazz_t::value>("value"_hs)
|
||||
.func<&clazz_t::member>("member"_hs)
|
||||
@@ -210,17 +216,16 @@ TEST_F(MetaType, Functionalities) {
|
||||
ASSERT_EQ(type.info(), entt::type_id<clazz_t>());
|
||||
|
||||
for(auto curr: type.prop()) {
|
||||
ASSERT_EQ(curr.key(), property_t::value);
|
||||
ASSERT_EQ(curr.value(), 42);
|
||||
ASSERT_EQ(curr.first, static_cast<entt::id_type>(property_t::value));
|
||||
ASSERT_EQ(curr.second.value(), 42);
|
||||
}
|
||||
|
||||
ASSERT_FALSE(type.prop(property_t::key_only));
|
||||
ASSERT_FALSE(type.prop(static_cast<entt::id_type>(property_t::key_only)));
|
||||
ASSERT_FALSE(type.prop("property"_hs));
|
||||
|
||||
auto prop = type.prop(property_t::value);
|
||||
auto prop = type.prop(static_cast<entt::id_type>(property_t::value));
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.key(), property_t::value);
|
||||
ASSERT_EQ(prop.value(), 42);
|
||||
}
|
||||
|
||||
@@ -498,7 +503,7 @@ TEST_F(MetaType, Reset) {
|
||||
|
||||
ASSERT_TRUE(entt::resolve("clazz"_hs));
|
||||
ASSERT_EQ(entt::resolve<clazz_t>().id(), "clazz"_hs);
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().prop(property_t::value));
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().prop(static_cast<entt::id_type>(property_t::value)));
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("value"_hs));
|
||||
ASSERT_TRUE((entt::resolve<clazz_t>().construct(derived_t{}, clazz_t{})));
|
||||
// implicitly generated default constructor
|
||||
@@ -508,7 +513,7 @@ TEST_F(MetaType, Reset) {
|
||||
|
||||
ASSERT_FALSE(entt::resolve("clazz"_hs));
|
||||
ASSERT_NE(entt::resolve<clazz_t>().id(), "clazz"_hs);
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().prop(property_t::value));
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().prop(static_cast<entt::id_type>(property_t::value)));
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().data("value"_hs));
|
||||
ASSERT_FALSE((entt::resolve<clazz_t>().construct(derived_t{}, clazz_t{})));
|
||||
// implicitly generated default constructor is not cleared
|
||||
@@ -612,21 +617,21 @@ TEST_F(MetaType, PropertiesAndCornerCases) {
|
||||
|
||||
auto type = entt::resolve<property_t>();
|
||||
|
||||
ASSERT_EQ(type.data("random"_hs).prop(property_t::random).value().cast<int>(), 0);
|
||||
ASSERT_EQ(type.data("random"_hs).prop(property_t::value).value().cast<int>(), 3);
|
||||
ASSERT_EQ(type.data("random"_hs).prop(static_cast<entt::id_type>(property_t::random)).value().cast<int>(), 0);
|
||||
ASSERT_EQ(type.data("random"_hs).prop(static_cast<entt::id_type>(property_t::value)).value().cast<int>(), 3);
|
||||
|
||||
ASSERT_EQ(type.data("value"_hs).prop(property_t::random).value().cast<bool>(), true);
|
||||
ASSERT_EQ(type.data("value"_hs).prop(property_t::value).value().cast<int>(), 0);
|
||||
ASSERT_TRUE(type.data("value"_hs).prop(property_t::key_only));
|
||||
ASSERT_FALSE(type.data("value"_hs).prop(property_t::key_only).value());
|
||||
ASSERT_EQ(type.data("value"_hs).prop(static_cast<entt::id_type>(property_t::random)).value().cast<bool>(), true);
|
||||
ASSERT_EQ(type.data("value"_hs).prop(static_cast<entt::id_type>(property_t::value)).value().cast<int>(), 0);
|
||||
ASSERT_TRUE(type.data("value"_hs).prop(static_cast<entt::id_type>(property_t::key_only)));
|
||||
ASSERT_FALSE(type.data("value"_hs).prop(static_cast<entt::id_type>(property_t::key_only)).value());
|
||||
|
||||
ASSERT_TRUE(type.data("key_only"_hs).prop(property_t::key_only));
|
||||
ASSERT_FALSE(type.data("key_only"_hs).prop(property_t::key_only).value());
|
||||
ASSERT_TRUE(type.data("key_only"_hs).prop(static_cast<entt::id_type>(property_t::key_only)));
|
||||
ASSERT_FALSE(type.data("key_only"_hs).prop(static_cast<entt::id_type>(property_t::key_only)).value());
|
||||
|
||||
ASSERT_EQ(type.data("list"_hs).prop(property_t::random).value().cast<bool>(), false);
|
||||
ASSERT_EQ(type.data("list"_hs).prop(property_t::value).value().cast<int>(), 0);
|
||||
ASSERT_TRUE(type.data("list"_hs).prop(property_t::key_only));
|
||||
ASSERT_FALSE(type.data("list"_hs).prop(property_t::key_only).value());
|
||||
ASSERT_EQ(type.data("list"_hs).prop(static_cast<entt::id_type>(property_t::random)).value().cast<bool>(), false);
|
||||
ASSERT_EQ(type.data("list"_hs).prop(static_cast<entt::id_type>(property_t::value)).value().cast<int>(), 0);
|
||||
ASSERT_TRUE(type.data("list"_hs).prop(static_cast<entt::id_type>(property_t::key_only)));
|
||||
ASSERT_FALSE(type.data("list"_hs).prop(static_cast<entt::id_type>(property_t::key_only)).value());
|
||||
}
|
||||
|
||||
TEST_F(MetaType, ResetAndReRegistrationAfterReset) {
|
||||
@@ -651,7 +656,7 @@ TEST_F(MetaType, ResetAndReRegistrationAfterReset) {
|
||||
|
||||
ASSERT_EQ(*entt::internal::meta_context::global(), nullptr);
|
||||
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().prop(property_t::value));
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().prop(static_cast<entt::id_type>(property_t::value)));
|
||||
// implicitly generated default constructor is not cleared
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().construct());
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().data("value"_hs));
|
||||
@@ -670,10 +675,11 @@ TEST_F(MetaType, ResetAndReRegistrationAfterReset) {
|
||||
entt::meta<property_t>()
|
||||
.type("property"_hs)
|
||||
.data<property_t::random>("rand"_hs)
|
||||
.props(std::make_pair(property_t::value, 42), std::make_pair(property_t::random, 3));
|
||||
.prop(static_cast<entt::id_type>(property_t::value), 42)
|
||||
.prop(static_cast<entt::id_type>(property_t::random), 3);
|
||||
|
||||
ASSERT_TRUE(entt::resolve<property_t>().data("rand"_hs).prop(property_t::value));
|
||||
ASSERT_TRUE(entt::resolve<property_t>().data("rand"_hs).prop(property_t::random));
|
||||
ASSERT_TRUE(entt::resolve<property_t>().data("rand"_hs).prop(static_cast<entt::id_type>(property_t::value)));
|
||||
ASSERT_TRUE(entt::resolve<property_t>().data("rand"_hs).prop(static_cast<entt::id_type>(property_t::random)));
|
||||
}
|
||||
|
||||
TEST_F(MetaType, ReRegistration) {
|
||||
|
||||
Reference in New Issue
Block a user