meta: add meta_type::can_convert (close #1028)

This commit is contained in:
skypjack
2023-07-25 09:58:58 +02:00
committed by Michele Caini
parent 1e65fede6c
commit 73dd3dcc26
3 changed files with 46 additions and 0 deletions

View File

@@ -1333,6 +1333,14 @@ public:
return internal::try_cast(internal::meta_context::from(*ctx), node, other.node, this);
}
/**
* @brief Checks if a type supports conversion it to another type.
* @return True if the conversion is allowed, false otherwise.
*/
[[nodiscard]] bool can_convert(const meta_type &other) const noexcept {
return internal::can_convert(internal::meta_context::from(*ctx), node, other.node);
}
/**
* @brief Returns a range to visit registered top-level base meta types.
* @return An iterable range to visit registered top-level base meta types.

View File

@@ -159,6 +159,26 @@ template<typename... Args>
return nullptr;
}
[[nodiscard]] inline bool can_convert(const meta_context &context, const meta_type_node &from, const meta_type_node &to) noexcept {
if((from.info && *from.info == *to.info) || (from.conversion_helper && static_cast<bool>(to.traits & (meta_traits::is_arithmetic | meta_traits::is_enum)))) {
return true;
}
if(from.details) {
if(auto it = from.details->conv.find(to.info->hash()); it != from.details->conv.cend()) {
return true;
}
for(auto &&curr: from.details->base) {
if(can_convert(context, curr.second.type(context), to)) {
return true;
}
}
}
return false;
}
[[nodiscard]] inline const meta_type_node *try_resolve(const meta_context &context, const type_info &info) noexcept {
const auto it = context.value.find(info.hash());
return it != context.value.end() ? &it->second : nullptr;

View File

@@ -311,6 +311,24 @@ TEST_F(MetaType, CanCast) {
ASSERT_TRUE(type.can_cast(entt::resolve<derived_t>()));
}
TEST_F(MetaType, CanConvert) {
auto clazz = entt::resolve<clazz_t>();
auto derived = entt::resolve<derived_t>();
auto arithmetic = entt::resolve<int>();
ASSERT_TRUE(clazz.can_convert(entt::resolve<clazz_t>()));
ASSERT_TRUE(clazz.can_convert(entt::resolve<int>()));
ASSERT_TRUE(derived.can_convert(entt::resolve<derived_t>()));
ASSERT_TRUE(derived.can_convert(entt::resolve<base_t>()));
ASSERT_FALSE(derived.can_convert(entt::resolve<int>()));
ASSERT_TRUE(arithmetic.can_convert(entt::resolve<int>()));
ASSERT_FALSE(arithmetic.can_convert(entt::resolve<clazz_t>()));
ASSERT_TRUE(arithmetic.can_convert(entt::resolve<double>()));
ASSERT_TRUE(arithmetic.can_convert(entt::resolve<float>()));
}
TEST_F(MetaType, Base) {
auto type = entt::resolve<derived_t>();