meta: support for dereferencing pointers to functions

This commit is contained in:
Michele Caini
2021-01-13 13:14:21 +01:00
parent 9b80c0028d
commit 39ecd1545c
2 changed files with 23 additions and 3 deletions

View File

@@ -357,7 +357,11 @@ class meta_any {
case operation::DEREF:
case operation::CDEREF:
if constexpr(is_meta_pointer_like_v<Type>) {
if constexpr(!std::is_same_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>, void>) {
using element_type = std::remove_const_t<typename std::pointer_traits<Type>::element_type>;
if constexpr(std::is_function_v<element_type>) {
*static_cast<meta_any *>(to) = any_cast<const Type>(from);
} else if constexpr(!std::is_same_v<element_type, void>) {
auto &&obj = adl_meta_pointer_like<Type>::dereference(any_cast<const Type>(from));
*static_cast<meta_any *>(to) = (op == operation::DEREF ? meta_any{std::reference_wrapper{obj}} : meta_any{std::cref(obj)});
}

View File

@@ -40,6 +40,8 @@ struct entt::adl_meta_pointer_like<spec_wrapped_shared_ptr<Type>> {
}
};
void test_function() {}
struct not_copyable_t {
not_copyable_t() = default;
not_copyable_t(const not_copyable_t &) = delete;
@@ -242,7 +244,7 @@ TEST(MetaPointerLike, DereferencePointerToConstOverload) {
test(spec_wrapped_shared_ptr<const int>{42});
}
TEST(MetaPointerLike, PointerToVoidSupport) {
TEST(MetaPointerLike, DereferencePointerToVoid) {
auto test = [](entt::meta_any any) {
ASSERT_TRUE(any.type().is_pointer());
ASSERT_TRUE(any.type().is_pointer_like());
@@ -257,7 +259,7 @@ TEST(MetaPointerLike, PointerToVoidSupport) {
test(static_cast<const void *>(nullptr));
}
TEST(MetaPointerLike, SmartPointerToVoidSupport) {
TEST(MetaPointerLike, DereferenceSmartPointerToVoid) {
auto test = [](entt::meta_any any) {
ASSERT_TRUE(any.type().is_class());
ASSERT_FALSE(any.type().is_pointer());
@@ -271,3 +273,17 @@ TEST(MetaPointerLike, SmartPointerToVoidSupport) {
test(std::shared_ptr<void>{});
test(std::unique_ptr<void, void(*)(void *)>{nullptr, nullptr});
}
TEST(MetaPointerLike, DereferencePointerToFunction) {
entt::meta_any any{&test_function};
ASSERT_TRUE(any.type().is_pointer());
ASSERT_TRUE(any.type().is_pointer_like());
ASSERT_EQ(any.type().remove_pointer(), entt::resolve<void()>());
auto deref = *any;
ASSERT_TRUE(deref.type().is_pointer());
ASSERT_TRUE(deref.type().is_pointer_like());
ASSERT_EQ(deref.type().remove_pointer(), entt::resolve<void()>());
}