meta: arrays are no longer indexable via meta_type::set/get

This commit is contained in:
Michele Caini
2020-06-12 09:30:29 +02:00
parent 7c21042858
commit bf3864b2da
4 changed files with 29 additions and 123 deletions

View File

@@ -76,59 +76,35 @@ template<typename Type, typename... Args, std::size_t... Indexes>
template<typename Type, auto Data>
[[nodiscard]] bool setter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any index, [[maybe_unused]] meta_any value) {
[[nodiscard]] bool setter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any value) {
bool accepted = false;
if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>> || std::is_member_function_pointer_v<decltype(Data)>) {
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>, "Invalid function or member function");
auto * const clazz = instance.try_cast<Type>();
auto * const direct = value.try_cast<data_type>();
if(clazz && (direct || value.convert<data_type>())) {
std::invoke(Data, *clazz, direct ? *direct : value.cast<data_type>());
accepted = true;
if(auto * const clazz = instance.try_cast<Type>(); clazz) {
if(auto * const direct = value.try_cast<data_type>(); direct || value.convert<data_type>()) {
std::invoke(Data, *clazz, direct ? *direct : value.cast<data_type>());
accepted = true;
}
}
} 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 *>, "Invalid data member");
auto * const clazz = instance.try_cast<Type>();
if constexpr(std::is_array_v<data_type>) {
using underlying_type = std::remove_extent_t<data_type>;
auto * const direct = value.try_cast<underlying_type>();
auto * const idx = index.try_cast<std::size_t>();
if(clazz && idx && (direct || value.convert<underlying_type>())) {
std::invoke(Data, clazz)[*idx] = direct ? *direct : value.cast<underlying_type>();
accepted = true;
}
} else {
auto * const direct = value.try_cast<data_type>();
if(clazz && (direct || value.convert<data_type>())) {
std::invoke(Data, clazz) = (direct ? *direct : value.cast<data_type>());
accepted = true;
if constexpr(!std::is_array_v<data_type>) {
if(auto * const clazz = instance.try_cast<Type>(); clazz) {
if(auto * const direct = value.try_cast<data_type>(); direct || value.convert<data_type>()) {
std::invoke(Data, clazz) = (direct ? *direct : value.cast<data_type>());
accepted = true;
}
}
}
} else {
static_assert(std::is_pointer_v<decltype(Data)>, "Invalid pointer to data type");
using data_type = std::remove_cv_t<std::remove_reference_t<decltype(*Data)>>;
if constexpr(std::is_array_v<data_type>) {
using underlying_type = std::remove_extent_t<data_type>;
auto * const direct = value.try_cast<underlying_type>();
auto * const idx = index.try_cast<std::size_t>();
if(idx && (direct || value.convert<underlying_type>())) {
(*Data)[*idx] = (direct ? *direct : value.cast<underlying_type>());
accepted = true;
}
} else {
auto * const direct = value.try_cast<data_type>();
if(direct || value.convert<data_type>()) {
if constexpr(!std::is_array_v<data_type>) {
if(auto * const direct = value.try_cast<data_type>(); direct || value.convert<data_type>()) {
*Data = (direct ? *direct : value.cast<data_type>());
accepted = true;
}
@@ -140,7 +116,7 @@ template<typename Type, auto Data>
template<typename Type, auto Data, typename Policy>
[[nodiscard]] meta_any getter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any index) {
[[nodiscard]] meta_any getter([[maybe_unused]] meta_any instance) {
auto dispatch = [](auto &&value) {
if constexpr(std::is_same_v<Policy, as_void_t>) {
return meta_any{std::in_place_type<void>, std::forward<decltype(value)>(value)};
@@ -153,24 +129,18 @@ template<typename Type, auto Data, typename Policy>
};
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 &>, "Invalid function or member function");
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 *>, "Invalid data member");
auto * const clazz = instance.try_cast<Type>();
if constexpr(std::is_array_v<data_type>) {
auto * const idx = index.try_cast<std::size_t>();
return (clazz && idx) ? dispatch(std::invoke(Data, clazz)[*idx]) : meta_any{};
if constexpr(std::is_array_v<std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>>) {
return meta_any{};
} else {
auto * const clazz = instance.try_cast<Type>();
return clazz ? dispatch(std::invoke(Data, clazz)) : meta_any{};
}
} else if constexpr(std::is_pointer_v<std::decay_t<decltype(Data)>>) {
if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) {
auto * const idx = index.try_cast<std::size_t>();
return idx ? dispatch((*Data)[*idx]) : meta_any{};
return meta_any{};
} else {
return dispatch(*Data);
}
@@ -666,7 +636,7 @@ public:
false,
&internal::meta_info<underlying_type>::resolve,
[]() -> decltype(internal::meta_data_node::set) {
if constexpr(std::is_same_v<decltype(Setter), std::nullptr_t> || (std::is_member_object_pointer_v<decltype(Setter)> && std::is_const_v<underlying_type>)) {
if constexpr(std::is_same_v<decltype(Setter), std::nullptr_t> || (std::is_member_object_pointer_v<decltype(Setter)> && std::is_const_v<underlying_type>)) {
return nullptr;
} else {
return &internal::setter<Type, Setter>;

View File

@@ -77,8 +77,8 @@ struct meta_data_node {
meta_prop_node * prop;
const bool is_static;
meta_type_node *(* const type)() ENTT_NOEXCEPT;
bool(* const set)(meta_any, meta_any, meta_any);
meta_any(* const get)(meta_any, meta_any);
bool(* const set)(meta_any, meta_any);
meta_any(* const get)(meta_any);
};

View File

@@ -711,28 +711,7 @@ struct meta_data {
*/
template<typename Type>
bool set(meta_handle instance, Type &&value) const {
return node->set && node->set(*instance, {}, std::forward<Type>(value));
}
/**
* @brief Sets the i-th element of a given array.
*
* It must be possible to cast the instance to the parent type of the meta
* data. Otherwise, invoking the setter results in an undefined
* behavior.<br/>
* The type of the value must be such that a cast or conversion to the array
* type is possible. Otherwise, invoking the setter does nothing.
*
* @tparam Type Type of value to assign.
* @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 instance, std::size_t index, Type &&value) const {
ENTT_ASSERT(index < node->type()->extent);
return node->set && node->set(*instance, index, std::forward<Type>(value));
return node->set && node->set(*instance, std::forward<Type>(value));
}
/**
@@ -745,22 +724,7 @@ struct meta_data {
* @return A meta any containing the value of the underlying variable.
*/
[[nodiscard]] meta_any get(meta_handle instance) const {
return node->get(*instance, {});
}
/**
* @brief Gets the i-th element of a given array.
*
* 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 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.
*/
[[nodiscard]] meta_any get(meta_handle instance, std::size_t index) const {
ENTT_ASSERT(index < node->type()->extent);
return node->get(*instance, index);
return node->get(*instance);
}
/*! @copydoc meta_ctor::prop */

View File

@@ -54,7 +54,7 @@ struct setter_getter_t {
struct array_t {
static inline int global[3];
int local[3];
int local[5];
};
enum class property_t {
@@ -347,10 +347,6 @@ TEST_F(MetaData, SetterGetterReadOnlyDataMember) {
TEST_F(MetaData, ArrayStatic) {
auto data = entt::resolve<array_t>().data("global"_hs);
array_t::global[0] = 3;
array_t::global[1] = 5;
array_t::global[2] = 7;
ASSERT_TRUE(data);
ASSERT_EQ(data.parent(), entt::resolve_id("array"_hs));
ASSERT_EQ(data.type(), entt::resolve<int[3]>());
@@ -359,46 +355,22 @@ TEST_F(MetaData, ArrayStatic) {
ASSERT_TRUE(data.is_static());
ASSERT_TRUE(data.type().is_array());
ASSERT_EQ(data.type().extent(), 3);
ASSERT_EQ(data.get({}, 0).cast<int>(), 3);
ASSERT_EQ(data.get({}, 1).cast<int>(), 5);
ASSERT_EQ(data.get({}, 2).cast<int>(), 7);
ASSERT_FALSE(data.set({}, 0, 'c'));
ASSERT_EQ(data.get({}, 0).cast<int>(), 3);
ASSERT_TRUE(data.set({}, 0, data.get({}, 0).cast<int>()+2));
ASSERT_TRUE(data.set({}, 1, data.get({}, 1).cast<int>()+2));
ASSERT_TRUE(data.set({}, 2, data.get({}, 2).cast<int>()+2));
ASSERT_EQ(data.get({}, 0).cast<int>(), 5);
ASSERT_EQ(data.get({}, 1).cast<int>(), 7);
ASSERT_EQ(data.get({}, 2).cast<int>(), 9);
ASSERT_FALSE(data.get({}));
}
TEST_F(MetaData, Array) {
auto data = entt::resolve<array_t>().data("local"_hs);
array_t instance;
instance.local[0] = 3;
instance.local[1] = 5;
instance.local[2] = 7;
ASSERT_TRUE(data);
ASSERT_EQ(data.parent(), entt::resolve_id("array"_hs));
ASSERT_EQ(data.type(), entt::resolve<int[3]>());
ASSERT_EQ(data.type(), entt::resolve<int[5]>());
ASSERT_EQ(data.id(), "local"_hs);
ASSERT_FALSE(data.is_const());
ASSERT_FALSE(data.is_static());
ASSERT_TRUE(data.type().is_array());
ASSERT_EQ(data.type().extent(), 3);
ASSERT_EQ(data.get(instance, 0).cast<int>(), 3);
ASSERT_EQ(data.get(instance, 1).cast<int>(), 5);
ASSERT_EQ(data.get(instance, 2).cast<int>(), 7);
ASSERT_FALSE(data.set(instance, 0, 'c'));
ASSERT_EQ(data.get(instance, 0).cast<int>(), 3);
ASSERT_TRUE(data.set(instance, 0, data.get(instance, 0).cast<int>()+2));
ASSERT_TRUE(data.set(instance, 1, data.get(instance, 1).cast<int>()+2));
ASSERT_TRUE(data.set(instance, 2, data.get(instance, 2).cast<int>()+2));
ASSERT_EQ(data.get(instance, 0).cast<int>(), 5);
ASSERT_EQ(data.get(instance, 1).cast<int>(), 7);
ASSERT_EQ(data.get(instance, 2).cast<int>(), 9);
ASSERT_EQ(data.type().extent(), 5);
ASSERT_FALSE(data.get(instance));
}
TEST_F(MetaData, AsVoid) {