소스 검색

meta: added support to self pointer in meta_any

Michele Caini 5 년 전
부모
커밋
1c1c3eb271
2개의 변경된 파일25개의 추가작업 그리고 5개의 파일을 삭제
  1. 1 1
      src/entt/meta/meta.hpp
  2. 24 4
      test/entt/meta/meta_pointer.cpp

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

@@ -378,7 +378,7 @@ class meta_any {
                 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));
+                    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)});
                 }
             }

+ 24 - 4
test/entt/meta/meta_pointer.cpp

@@ -16,6 +16,12 @@ private:
     std::shared_ptr<Type> ptr;
 };
 
+struct self {
+    using element_type = int;
+    const self & operator*() const { return *this; }
+    int value{};
+};
+
 template<typename Type>
 struct adl_wrapped_shared_ptr: wrapped_shared_ptr<Type> {};
 
@@ -28,10 +34,8 @@ struct entt::is_meta_pointer_like<adl_wrapped_shared_ptr<Type>>: std::true_type
 template<typename Type>
 struct entt::is_meta_pointer_like<spec_wrapped_shared_ptr<Type>>: std::true_type {};
 
-template<typename Type>
-Type & dereference_meta_pointer_like(const adl_wrapped_shared_ptr<Type> &ptr) {
-    return ptr.deref();
-}
+template<>
+struct entt::is_meta_pointer_like<self>: std::true_type {};
 
 template<typename Type>
 struct entt::adl_meta_pointer_like<spec_wrapped_shared_ptr<Type>> {
@@ -40,6 +44,11 @@ struct entt::adl_meta_pointer_like<spec_wrapped_shared_ptr<Type>> {
     }
 };
 
+template<typename Type>
+Type & dereference_meta_pointer_like(const adl_wrapped_shared_ptr<Type> &ptr) {
+    return ptr.deref();
+}
+
 int test_function() { return 42; }
 
 struct not_copyable_t {
@@ -287,3 +296,14 @@ TEST(MetaPointerLike, DereferencePointerToFunction) {
     test(*entt::meta_any{&test_function});
     test(**entt::meta_any{&test_function});
 }
+
+TEST(MetaPointerLike, DereferenceSelfPointer) {
+    self obj{42};
+    entt::meta_any any{std::ref(obj)};
+    entt::meta_any deref = *any;
+
+    ASSERT_TRUE(deref);
+    ASSERT_TRUE(any.type().is_pointer_like());
+    ASSERT_FALSE(deref.try_cast<self>());
+    ASSERT_EQ(deref.cast<const self &>().value, obj.value);
+}