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

meta: support for proxy pointers

Michele Caini 5 лет назад
Родитель
Сommit
b90b71c8c0
2 измененных файлов с 41 добавлено и 11 удалено
  1. 6 2
      src/entt/meta/meta.hpp
  2. 35 9
      test/entt/meta/meta_pointer.cpp

+ 6 - 2
src/entt/meta/meta.hpp

@@ -172,8 +172,12 @@ 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));
-                    *static_cast<meta_any *>(to) = (op == operation::DEREF ? meta_any{std::reference_wrapper{obj}} : meta_any{std::cref(obj)});
+                    if constexpr(std::is_reference_v<decltype(adl_meta_pointer_like<Type>::dereference(std::declval<const Type &>()))>) {
+                        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)});
+                    } else {
+                        *static_cast<meta_any *>(to) = adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(from));
+                    }
                 }
             }
             break;

+ 35 - 9
test/entt/meta/meta_pointer.cpp

@@ -15,13 +15,20 @@ private:
     std::shared_ptr<Type> ptr;
 };
 
-struct self {
-    using element_type = int;
-    self(int v): value{v} {}
-    const self & operator*() const { return *this; }
+struct self_ptr {
+    using element_type = self_ptr;
+    self_ptr(int v): value{v} {}
+    const self_ptr & operator*() const { return *this; }
     int value;
 };
 
+struct proxy_ptr {
+    using element_type = proxy_ptr;
+    proxy_ptr(int &v): value{&v} {}
+    proxy_ptr operator*() const { return *this; }
+    int *value;
+};
+
 template<typename Type>
 struct adl_wrapped_shared_ptr: wrapped_shared_ptr<Type> {};
 
@@ -35,7 +42,10 @@ template<typename Type>
 struct entt::is_meta_pointer_like<spec_wrapped_shared_ptr<Type>>: std::true_type {};
 
 template<>
-struct entt::is_meta_pointer_like<self>: std::true_type {};
+struct entt::is_meta_pointer_like<self_ptr>: std::true_type {};
+
+template<>
+struct entt::is_meta_pointer_like<proxy_ptr>: std::true_type {};
 
 template<typename Type>
 struct entt::adl_meta_pointer_like<spec_wrapped_shared_ptr<Type>> {
@@ -298,12 +308,28 @@ TEST(MetaPointerLike, DereferencePointerToFunction) {
 }
 
 TEST(MetaPointerLike, DereferenceSelfPointer) {
-    self obj{42};
+    self_ptr 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);
-}
+    ASSERT_EQ(deref.cast<const self_ptr &>().value, obj.value);
+    ASSERT_FALSE(deref.try_cast<self_ptr>());
+}
+
+TEST(MetaPointerLike, DereferenceProxyPointer) {
+    int value = 3;
+    proxy_ptr obj{value};
+    entt::meta_any any{obj};
+    entt::meta_any deref = *any;
+
+    ASSERT_TRUE(deref);
+    ASSERT_TRUE(any.type().is_pointer_like());
+    ASSERT_EQ(*deref.cast<const proxy_ptr &>().value, value);
+    ASSERT_TRUE(deref.try_cast<proxy_ptr>());
+
+    *deref.cast<proxy_ptr &>().value = 42;
+
+    ASSERT_EQ(value, 42);
+}