Quellcode durchsuchen

meta: support transparently base members when attached to meta types for derived classes

Michele Caini vor 4 Jahren
Ursprung
Commit
b13713ce98
3 geänderte Dateien mit 72 neuen und 15 gelöschten Zeilen
  1. 8 8
      src/entt/meta/utility.hpp
  2. 18 2
      test/entt/meta/meta_data.cpp
  3. 46 5
      test/entt/meta/meta_func.cpp

+ 8 - 8
src/entt/meta/utility.hpp

@@ -28,12 +28,12 @@ struct meta_function_descriptor<Type, Ret (Class::*)(Args...) const> {
     /*! @brief Meta function return type. */
     using return_type = Ret;
     /*! @brief Meta function arguments. */
-    using args_type = std::conditional_t<std::is_same_v<Type, Class>, type_list<Args...>, type_list<const Class &, Args...>>;
+    using args_type = std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<const Class &, Args...>>;
 
     /*! @brief True if the meta function is const, false otherwise. */
     static constexpr auto is_const = true;
     /*! @brief True if the meta function is static, false otherwise. */
-    static constexpr auto is_static = !std::is_same_v<Type, Class>;
+    static constexpr auto is_static = !std::is_base_of_v<Class, Type>;
 };
 
 /**
@@ -48,12 +48,12 @@ struct meta_function_descriptor<Type, Ret (Class::*)(Args...)> {
     /*! @brief Meta function return type. */
     using return_type = Ret;
     /*! @brief Meta function arguments. */
-    using args_type = std::conditional_t<std::is_same_v<Type, Class>, type_list<Args...>, type_list<Class &, Args...>>;
+    using args_type = std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<Class &, Args...>>;
 
     /*! @brief True if the meta function is const, false otherwise. */
     static constexpr auto is_const = false;
     /*! @brief True if the meta function is static, false otherwise. */
-    static constexpr auto is_static = !std::is_same_v<Type, Class>;
+    static constexpr auto is_static = !std::is_base_of_v<Class, Type>;
 };
 
 /**
@@ -67,7 +67,7 @@ struct meta_function_descriptor<Type, Ret Class::*> {
     /*! @brief Meta data return type. */
     using return_type = Ret;
     /*! @brief Meta data arguments. */
-    using args_type = std::conditional_t<std::is_same_v<Type, Class>, type_list<Ret>, type_list<Class &, Ret>>;
+    using args_type = std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Ret>, type_list<Class &, Ret>>;
 
     /*! @brief True if the meta data is const, false otherwise. */
     static constexpr auto is_const = false;
@@ -87,12 +87,12 @@ struct meta_function_descriptor<Type, Ret (*)(MaybeType, Args...)> {
     /*! @brief Meta function return type. */
     using return_type = Ret;
     /*! @brief Meta function arguments. */
-    using args_type = std::conditional_t<std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<MaybeType>>>, type_list<Args...>, type_list<MaybeType, Args...>>;
+    using args_type = std::conditional_t<std::is_base_of_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type>, type_list<Args...>, type_list<MaybeType, Args...>>;
 
     /*! @brief True if the meta function is const, false otherwise. */
-    static constexpr auto is_const = std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<MaybeType>>> && std::is_const_v<std::remove_reference_t<MaybeType>>;
+    static constexpr auto is_const = std::is_base_of_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type> && std::is_const_v<std::remove_reference_t<MaybeType>>;
     /*! @brief True if the meta function is static, false otherwise. */
-    static constexpr auto is_static = !std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<MaybeType>>>;
+    static constexpr auto is_static = !std::is_base_of_v<std::remove_const_t<std::remove_reference_t<MaybeType>>, Type>;
 };
 
 /**

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

@@ -109,7 +109,8 @@ struct MetaData: ::testing::Test {
         entt::meta<derived_t>()
             .type("derived"_hs)
             .base<base_t>()
-            .dtor<derived_t::destroy>();
+            .dtor<derived_t::destroy>()
+            .data<&base_t::value>("value_from_base"_hs);
 
         entt::meta<clazz_t>()
             .type("clazz"_hs)
@@ -612,7 +613,7 @@ TEST_F(MetaData, AsConstRef) {
     ASSERT_EQ(instance.i, 0);
 }
 
-TEST_F(MetaData, FromBase) {
+TEST_F(MetaData, SetGetBaseData) {
     using namespace entt::literals;
 
     auto type = entt::resolve<derived_t>();
@@ -622,6 +623,21 @@ TEST_F(MetaData, FromBase) {
 
     ASSERT_EQ(instance.value, 3);
     ASSERT_TRUE(type.data("value"_hs).set(instance, 42));
+    ASSERT_EQ(type.data("value"_hs).get(instance).cast<int>(), 42);
+    ASSERT_EQ(instance.value, 42);
+}
+
+TEST_F(MetaData, SetGetFromBase) {
+    using namespace entt::literals;
+
+    auto type = entt::resolve<derived_t>();
+    derived_t instance{};
+
+    ASSERT_TRUE(type.data("value_from_base"_hs));
+
+    ASSERT_EQ(instance.value, 3);
+    ASSERT_TRUE(type.data("value_from_base"_hs).set(instance, 42));
+    ASSERT_EQ(type.data("value_from_base"_hs).get(instance).cast<int>(), 42);
     ASSERT_EQ(instance.value, 42);
 }
 

+ 46 - 5
test/entt/meta/meta_func.cpp

@@ -14,10 +14,18 @@ struct base_t {
         ++counter;
     }
 
-    void func(int v) {
+    void setter(int v) {
         value = v;
     }
 
+    int getter() const {
+        return value;
+    }
+
+    static void static_setter(base_t &ref, int v) {
+        ref.value = v;
+    }
+
     inline static int counter = 0;
     int value{3};
 };
@@ -86,13 +94,16 @@ struct MetaFunc: ::testing::Test {
         entt::meta<base_t>()
             .type("base"_hs)
             .dtor<base_t::destroy>()
-            .func<&base_t::func>("func"_hs)
+            .func<&base_t::setter>("setter"_hs)
             .func<fake_member>("fake_member"_hs)
             .func<fake_const_member>("fake_const_member"_hs);
 
         entt::meta<derived_t>()
             .type("derived"_hs)
             .base<base_t>()
+            .func<&base_t::setter>("setter_from_base"_hs)
+            .func<&base_t::getter>("getter_from_base"_hs)
+            .func<&base_t::static_setter>("static_setter_from_base"_hs)
             .dtor<derived_t::destroy>();
 
         entt::meta<func_t>()
@@ -474,20 +485,50 @@ TEST_F(MetaFunc, AsConstRef) {
     ASSERT_EQ(func.invoke(instance).cast<int>(), 3);
 }
 
-TEST_F(MetaFunc, FromBase) {
+TEST_F(MetaFunc, InvokeBaseFunction) {
     using namespace entt::literals;
 
     auto type = entt::resolve<derived_t>();
     derived_t instance{};
 
-    ASSERT_TRUE(type.func("func"_hs));
+    ASSERT_TRUE(type.func("setter"_hs));
     ASSERT_EQ(instance.value, 3);
 
-    type.func("func"_hs).invoke(instance, 42);
+    type.func("setter"_hs).invoke(instance, 42);
 
     ASSERT_EQ(instance.value, 42);
 }
 
+TEST_F(MetaFunc, InvokeFromBase) {
+    using namespace entt::literals;
+
+    auto type = entt::resolve<derived_t>();
+    derived_t instance{};
+
+    auto setter_from_base = type.func("setter_from_base"_hs);
+
+    ASSERT_TRUE(setter_from_base);
+    ASSERT_EQ(instance.value, 3);
+
+    setter_from_base.invoke(instance, 42);
+
+    ASSERT_EQ(instance.value, 42);
+
+    auto getter_from_base = type.func("getter_from_base"_hs);
+
+    ASSERT_TRUE(getter_from_base);
+    ASSERT_EQ(getter_from_base.invoke(instance).cast<int>(), 42);
+
+    auto static_setter_from_base = type.func("static_setter_from_base"_hs);
+
+    ASSERT_TRUE(static_setter_from_base);
+    ASSERT_EQ(instance.value, 42);
+
+    static_setter_from_base.invoke(instance, 3);
+
+    ASSERT_EQ(instance.value, 3);
+}
+
 TEST_F(MetaFunc, ExternalMemberFunction) {
     using namespace entt::literals;