Просмотр исходного кода

meta: support for dereferencing pointers to functions

Michele Caini 5 лет назад
Родитель
Сommit
39ecd1545c
2 измененных файлов с 23 добавлено и 3 удалено
  1. 5 1
      src/entt/meta/meta.hpp
  2. 18 2
      test/entt/meta/meta_pointer.cpp

+ 5 - 1
src/entt/meta/meta.hpp

@@ -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)});
                 }

+ 18 - 2
test/entt/meta/meta_pointer.cpp

@@ -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()>());
+}