From b13713ce98c6dc6f8cd56b5aad237d3bd42056cc Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Tue, 26 Oct 2021 11:03:29 +0200 Subject: [PATCH] meta: support transparently base members when attached to meta types for derived classes --- src/entt/meta/utility.hpp | 16 +++++------ test/entt/meta/meta_data.cpp | 20 ++++++++++++-- test/entt/meta/meta_func.cpp | 51 ++++++++++++++++++++++++++++++++---- 3 files changed, 72 insertions(+), 15 deletions(-) diff --git a/src/entt/meta/utility.hpp b/src/entt/meta/utility.hpp index fefefd216..d162ab75c 100644 --- a/src/entt/meta/utility.hpp +++ b/src/entt/meta/utility.hpp @@ -28,12 +28,12 @@ struct meta_function_descriptor { /*! @brief Meta function return type. */ using return_type = Ret; /*! @brief Meta function arguments. */ - using args_type = std::conditional_t, type_list, type_list>; + using args_type = std::conditional_t, type_list, type_list>; /*! @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; + static constexpr auto is_static = !std::is_base_of_v; }; /** @@ -48,12 +48,12 @@ struct meta_function_descriptor { /*! @brief Meta function return type. */ using return_type = Ret; /*! @brief Meta function arguments. */ - using args_type = std::conditional_t, type_list, type_list>; + using args_type = std::conditional_t, type_list, type_list>; /*! @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; + static constexpr auto is_static = !std::is_base_of_v; }; /** @@ -67,7 +67,7 @@ struct meta_function_descriptor { /*! @brief Meta data return type. */ using return_type = Ret; /*! @brief Meta data arguments. */ - using args_type = std::conditional_t, type_list, type_list>; + using args_type = std::conditional_t, type_list, type_list>; /*! @brief True if the meta data is const, false otherwise. */ static constexpr auto is_const = false; @@ -87,12 +87,12 @@ struct meta_function_descriptor { /*! @brief Meta function return type. */ using return_type = Ret; /*! @brief Meta function arguments. */ - using args_type = std::conditional_t>>, type_list, type_list>; + using args_type = std::conditional_t>, Type>, type_list, type_list>; /*! @brief True if the meta function is const, false otherwise. */ - static constexpr auto is_const = std::is_same_v>> && std::is_const_v>; + static constexpr auto is_const = std::is_base_of_v>, Type> && std::is_const_v>; /*! @brief True if the meta function is static, false otherwise. */ - static constexpr auto is_static = !std::is_same_v>>; + static constexpr auto is_static = !std::is_base_of_v>, Type>; }; /** diff --git a/test/entt/meta/meta_data.cpp b/test/entt/meta/meta_data.cpp index c49e43902..8c0146b3d 100644 --- a/test/entt/meta/meta_data.cpp +++ b/test/entt/meta/meta_data.cpp @@ -109,7 +109,8 @@ struct MetaData: ::testing::Test { entt::meta() .type("derived"_hs) .base() - .dtor(); + .dtor() + .data<&base_t::value>("value_from_base"_hs); entt::meta() .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(); @@ -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(), 42); + ASSERT_EQ(instance.value, 42); +} + +TEST_F(MetaData, SetGetFromBase) { + using namespace entt::literals; + + auto type = entt::resolve(); + 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(), 42); ASSERT_EQ(instance.value, 42); } diff --git a/test/entt/meta/meta_func.cpp b/test/entt/meta/meta_func.cpp index e7c01929c..a3eeee8e1 100644 --- a/test/entt/meta/meta_func.cpp +++ b/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() .type("base"_hs) .dtor() - .func<&base_t::func>("func"_hs) + .func<&base_t::setter>("setter"_hs) .func("fake_member"_hs) .func("fake_const_member"_hs); entt::meta() .type("derived"_hs) .base() + .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(); entt::meta() @@ -474,20 +485,50 @@ TEST_F(MetaFunc, AsConstRef) { ASSERT_EQ(func.invoke(instance).cast(), 3); } -TEST_F(MetaFunc, FromBase) { +TEST_F(MetaFunc, InvokeBaseFunction) { using namespace entt::literals; auto type = entt::resolve(); 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 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(), 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;