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

meta_any: make ref to pointer-like types work in all cases

Michele Caini 5 лет назад
Родитель
Сommit
fa4c6bccbc
3 измененных файлов с 56 добавлено и 3 удалено
  1. 1 1
      src/entt/meta/meta.hpp
  2. 9 0
      src/entt/meta/type_traits.hpp
  3. 46 2
      test/entt/meta/meta_pointer.cpp

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

@@ -215,7 +215,7 @@ public:
     template<typename Type>
     meta_any(std::reference_wrapper<Type> value)
         : storage{value},
-          vtable{&basic_vtable<std::remove_const_t<Type>>},
+          vtable{&basic_vtable<Type>},
           node{internal::meta_info<Type>::resolve()}
     {}
 

+ 9 - 0
src/entt/meta/type_traits.hpp

@@ -105,6 +105,15 @@ template<typename>
 struct is_meta_pointer_like: std::false_type {};
 
 
+/**
+ * @brief Partial specialization to ensure that const pointer-like types are
+ * also accepted.
+ * @tparam Type Potentially pointer-like type.
+ */
+template<typename Type>
+struct is_meta_pointer_like<const Type>: is_meta_pointer_like<Type> {};
+
+
 /**
  * @brief Helper variable template.
  * @tparam Type Potentially pointer-like type.

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

@@ -42,7 +42,7 @@ TEST(MetaPointerLike, DereferenceOperatorConstType) {
 
     ASSERT_EQ(deref.try_cast<int>(), nullptr);
     ASSERT_EQ(deref.try_cast<const int>(), &value);
-    ASSERT_DEATH(deref.cast<int &>(), ".*");
+    ASSERT_DEATH(deref.cast<int &>() = 0, ".*");
     ASSERT_EQ(deref.cast<const int &>(), 42);
 }
 
@@ -96,7 +96,51 @@ TEST(MetaPointerLike, PointerToConstMoveOnlyType) {
     ASSERT_TRUE(any);
     ASSERT_TRUE(deref);
 
-    ASSERT_DEATH(deref.cast<not_copyable_t &>(), ".*");
+    ASSERT_DEATH(deref.cast<not_copyable_t &>() = {}, ".*");
     ASSERT_EQ(deref.try_cast<not_copyable_t>(), nullptr);
     ASSERT_NE(deref.try_cast<const not_copyable_t>(), nullptr);
 }
+
+TEST(MetaPointerLike, AsRef) {
+    int value = 0;
+    int * ptr = &value;
+    entt::meta_any any{std::ref(ptr)};
+
+    ASSERT_TRUE(any.type().is_pointer());
+    ASSERT_TRUE(any.type().is_pointer_like());
+    ASSERT_EQ(any.type(), entt::resolve<int *>());
+
+    auto deref = *any;
+
+    ASSERT_TRUE(deref);
+    ASSERT_FALSE(deref.type().is_pointer());
+    ASSERT_FALSE(deref.type().is_pointer_like());
+    ASSERT_EQ(deref.type(), entt::resolve<int>());
+
+    deref.cast<int &>() = 42;
+
+    ASSERT_EQ(*any.cast<int *>(), 42);
+    ASSERT_EQ(value, 42);
+}
+
+TEST(MetaPointerLike, AsConstRef) {
+    int value = 42;
+    int * ptr = &value;
+    entt::meta_any any{std::cref(ptr)};
+
+    ASSERT_TRUE(any.type().is_pointer());
+    ASSERT_TRUE(any.type().is_pointer_like());
+    ASSERT_EQ(any.type(), entt::resolve<int *>());
+
+    auto deref = *any;
+
+    ASSERT_TRUE(deref);
+    ASSERT_FALSE(deref.type().is_pointer());
+    ASSERT_FALSE(deref.type().is_pointer_like());
+    ASSERT_EQ(deref.type(), entt::resolve<int>());
+
+    deref.cast<int &>() = 42;
+
+    ASSERT_EQ(*any.cast<int *>(), 42);
+    ASSERT_EQ(value, 42);
+}