Bladeren bron

meta: pointer vs pointer-like rework (prepare to support all dereferenceable types)

skypjack 2 weken geleden
bovenliggende
commit
c6a8cf3de6

+ 21 - 25
src/entt/meta/meta.hpp

@@ -184,39 +184,35 @@ class meta_any {
         }
 
         if constexpr(is_meta_pointer_like_v<Type>) {
-            if(!!(req & internal::meta_traits::is_pointer_like)) {
-                if constexpr(std::is_function_v<typename std::pointer_traits<Type>::element_type>) {
-                    static_cast<meta_any *>(other)->emplace<Type>(any_cast<Type>(value.storage));
-                } else if constexpr(!std::is_void_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) {
-                    using in_place_type = decltype(adl_meta_pointer_like<Type>::dereference(std::declval<const Type &>()));
-
+            if(req == internal::meta_traits::is_pointer) {
+                if constexpr(!std::is_void_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) {
                     if constexpr(std::is_constructible_v<bool, Type>) {
                         if(const auto &pointer_like = any_cast<const Type &>(value.storage); pointer_like) {
-                            static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(pointer_like));
+                            static_cast<meta_any *>(other)->emplace<decltype(adl_meta_pointer_like<Type>::dereference(std::declval<const Type &>()))>(adl_meta_pointer_like<Type>::dereference(pointer_like));
                         }
                     } else {
-                        static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(value.storage)));
+                        static_cast<meta_any *>(other)->emplace<decltype(adl_meta_pointer_like<Type>::dereference(std::declval<const Type &>()))>(adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(value.storage)));
                     }
                 }
             }
-        }
-
-        if constexpr(is_complete_v<meta_sequence_container_traits<Type>> || is_complete_v<meta_associative_container_traits<Type>>) {
-            if(constexpr auto flag = (is_complete_v<meta_sequence_container_traits<Type>> ? internal::meta_traits::is_sequence_container : internal::meta_traits::is_associative_container); !!(req & flag)) {
-                using container_type = std::conditional_t<is_complete_v<meta_sequence_container_traits<Type>>, meta_sequence_container, meta_associative_container>;
-
-                if(!!(req & internal::meta_traits::is_const) || (value.storage.policy() == any_policy::cref)) {
-                    // NOLINTNEXTLINE(bugprone-casting-through-void)
-                    *static_cast<container_type *>(other) = container_type{*value.ctx, any_cast<const Type &>(value.storage)};
-                } else {
-                    // NOLINTNEXTLINE(bugprone-casting-through-void)
-                    *static_cast<container_type *>(other) = container_type{*value.ctx, any_cast<Type &>(const_cast<meta_any &>(value).storage)};
+        } else if constexpr(requires(Type elem) { *elem; }) {
+            if(req == internal::meta_traits::is_pointer) {
+                if constexpr(std::is_pointer_v<Type> && !std::is_void_v<std::remove_const_t<std::remove_pointer_t<Type>>>) {
+                    if(auto *pointer = any_cast<Type>(value.storage); pointer) {
+                        static_cast<meta_any *>(other)->emplace<std::conditional_t<std::is_function_v<std::remove_const_t<std::remove_pointer_t<Type>>>, Type, std::remove_pointer_t<Type> &>>(*pointer);
+                    }
                 }
             }
+        } else if constexpr(is_complete_v<meta_sequence_container_traits<Type>> || is_complete_v<meta_associative_container_traits<Type>>) {
+            if(constexpr auto flag = (is_complete_v<meta_sequence_container_traits<Type>> ? internal::meta_traits::is_sequence_container : internal::meta_traits::is_associative_container); req == flag) {
+                using container_type = std::conditional_t<is_complete_v<meta_sequence_container_traits<Type>>, meta_sequence_container, meta_associative_container>;
+                *static_cast<container_type *>(other) = (value.storage.policy() == any_policy::cref) ? container_type{*value.ctx, any_cast<const Type &>(value.storage)} : container_type{*value.ctx, any_cast<Type &>(const_cast<meta_any &>(value).storage)};
+            }
         }
     }
 
-    [[nodiscard]] const auto &fetch_node() const {
+    [[nodiscard]] const auto &
+    fetch_node() const {
         if(node == nullptr) {
             ENTT_ASSERT(*this, "Invalid vtable function");
             vtable(internal::meta_traits::is_none, *this, nullptr);
@@ -583,7 +579,7 @@ public:
     /*! @copydoc as_sequence_container */
     [[nodiscard]] meta_sequence_container as_sequence_container() const noexcept {
         meta_sequence_container proxy{};
-        if(*this) { vtable(internal::meta_traits::is_sequence_container | internal::meta_traits::is_const, *this, &proxy); }
+        if(*this) { vtable(internal::meta_traits::is_sequence_container, as_ref(), &proxy); }
         return proxy;
     }
 
@@ -600,7 +596,7 @@ public:
     /*! @copydoc as_associative_container */
     [[nodiscard]] meta_associative_container as_associative_container() const noexcept {
         meta_associative_container proxy{};
-        if(*this) { vtable(internal::meta_traits::is_associative_container | internal::meta_traits::is_const, *this, &proxy); }
+        if(*this) { vtable(internal::meta_traits::is_associative_container, as_ref(), &proxy); }
         return proxy;
     }
 
@@ -611,14 +607,14 @@ public:
      */
     [[nodiscard]] meta_any operator*() noexcept {
         meta_any ret{meta_ctx_arg, *ctx};
-        if(*this) { vtable(internal::meta_traits::is_pointer_like, *this, &ret); }
+        if(*this) { vtable(internal::meta_traits::is_pointer, *this, &ret); }
         return ret;
     }
 
     /*! @copydoc operator* */
     [[nodiscard]] meta_any operator*() const noexcept {
         meta_any ret{meta_ctx_arg, *ctx};
-        if(*this) { vtable(internal::meta_traits::is_pointer_like | internal::meta_traits::is_const, *this, &ret); }
+        if(*this) { vtable(internal::meta_traits::is_pointer, as_ref(), &ret); }
         return ret;
     }
 

+ 0 - 18
src/entt/meta/pointer.hpp

@@ -9,24 +9,6 @@
 
 namespace entt {
 
-/**
- * @brief Makes plain pointers pointer-like types for the meta system.
- * @tparam Type Element type.
- */
-template<typename Type>
-struct is_meta_pointer_like<Type *>
-    : std::true_type {};
-
-/**
- * @brief Partial specialization used to reject pointers to arrays.
- * @tparam Type Type of elements of the array.
- * @tparam N Number of elements of the array.
- */
-template<typename Type, std::size_t N>
-// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays)
-struct is_meta_pointer_like<Type (*)[N]>
-    : std::false_type {};
-
 /**
  * @brief Makes `std::shared_ptr`s of any type pointer-like types for the meta
  * system.

+ 2 - 2
test/entt/meta/meta_context.cpp

@@ -379,8 +379,8 @@ TEST_F(MetaContext, MetaPointer) {
     ASSERT_TRUE(global.type().is_pointer());
     ASSERT_TRUE(local.type().is_pointer());
 
-    ASSERT_TRUE(global.type().is_pointer_like());
-    ASSERT_TRUE(local.type().is_pointer_like());
+    ASSERT_FALSE(global.type().is_pointer_like());
+    ASSERT_FALSE(local.type().is_pointer_like());
 
     ASSERT_EQ((*global).type().data("marker"_hs).get({}).cast<int>(), global_marker);
     ASSERT_EQ((*local).type().data("marker"_hs).get({}).cast<int>(), local_marker);

+ 7 - 7
test/entt/meta/meta_dereference.cpp

@@ -108,7 +108,7 @@ TEST_F(MetaDereference, ConstType) {
     const entt::meta_any any{&value};
 
     ASSERT_TRUE(any.type().is_pointer());
-    ASSERT_TRUE(any.type().is_pointer_like());
+    ASSERT_FALSE(any.type().is_pointer_like());
     ASSERT_EQ(any.type(), entt::resolve<const int *>());
 
     auto deref = *any;
@@ -177,7 +177,7 @@ TEST_F(MetaDereference, RawPointer) {
     entt::meta_any any{&value};
 
     ASSERT_TRUE(any.type().is_pointer());
-    ASSERT_TRUE(any.type().is_pointer_like());
+    ASSERT_FALSE(any.type().is_pointer_like());
     ASSERT_EQ(any.type(), entt::resolve<int *>());
 
     auto deref = *any;
@@ -233,7 +233,7 @@ TEST_F(MetaDereference, AsRef) {
     entt::meta_any any{entt::forward_as_meta(ptr)};
 
     ASSERT_TRUE(any.type().is_pointer());
-    ASSERT_TRUE(any.type().is_pointer_like());
+    ASSERT_FALSE(any.type().is_pointer_like());
     ASSERT_EQ(any.type(), entt::resolve<int *>());
 
     auto deref = *any;
@@ -255,7 +255,7 @@ TEST_F(MetaDereference, AsConstRef) {
     entt::meta_any any{entt::forward_as_meta(ptr)};
 
     ASSERT_TRUE(any.type().is_pointer());
-    ASSERT_TRUE(any.type().is_pointer_like());
+    ASSERT_FALSE(any.type().is_pointer_like());
     ASSERT_EQ(any.type(), entt::resolve<int *>());
 
     auto deref = *any;
@@ -357,7 +357,7 @@ TEST_F(MetaDereference, PointerToVoid) {
     const entt::meta_any any{static_cast<void *>(nullptr)};
 
     ASSERT_TRUE(any.type().is_pointer());
-    ASSERT_TRUE(any.type().is_pointer_like());
+    ASSERT_FALSE(any.type().is_pointer_like());
 
     auto deref = *any;
 
@@ -368,7 +368,7 @@ TEST_F(MetaDereference, PointerToConstVoid) {
     const entt::meta_any any{static_cast<const void *>(nullptr)};
 
     ASSERT_TRUE(any.type().is_pointer());
-    ASSERT_TRUE(any.type().is_pointer_like());
+    ASSERT_FALSE(any.type().is_pointer_like());
 
     auto deref = *any;
 
@@ -403,7 +403,7 @@ TEST_F(MetaDereference, PointerToFunction) {
     entt::meta_any any{&test_function};
 
     ASSERT_TRUE(any.type().is_pointer());
-    ASSERT_TRUE((*std::as_const(any)).type().is_pointer_like());
+    ASSERT_FALSE((*std::as_const(any)).type().is_pointer_like());
     ASSERT_NE((**any).try_cast<int (*)()>(), nullptr);
     ASSERT_EQ((***std::as_const(any)).cast<int (*)()>()(), 3);
 }

+ 1 - 1
test/entt/meta/meta_type.cpp

@@ -357,7 +357,7 @@ TEST_F(MetaType, Traits) {
     ASSERT_TRUE(entt::resolve<int *>().is_pointer());
     ASSERT_FALSE(entt::resolve<int>().is_pointer());
 
-    ASSERT_TRUE(entt::resolve<int *>().is_pointer_like());
+    ASSERT_FALSE(entt::resolve<int *>().is_pointer_like());
     ASSERT_TRUE(entt::resolve<std::shared_ptr<int>>().is_pointer_like());
     ASSERT_FALSE(entt::resolve<int>().is_pointer_like());