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

setters/getters correctly handle references now (#fix 196)

Michele Caini 7 лет назад
Родитель
Сommit
b0d3a84d1e
2 измененных файлов с 45 добавлено и 31 удалено
  1. 24 30
      src/entt/meta/meta.hpp
  2. 21 1
      test/entt/meta/meta.cpp

+ 24 - 30
src/entt/meta/meta.hpp

@@ -2034,49 +2034,43 @@ inline meta_any construct(meta_any * const args, std::index_sequence<Indexes...>
 
 template<bool Const, typename Type, auto Data>
 bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any &any) {
+    bool accepted = false;
+
     if constexpr(Const) {
         return false;
-    } else if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Data)>> || std::is_member_pointer_v<decltype(Data)>) {
-        auto execute = [&handle, &any](auto *tag) {
-            using data_type = std::remove_pointer_t<decltype(tag)>;
-            const bool accepted = any.can_cast<data_type>() || any.convert<data_type>();
-            auto *clazz = handle.try_cast<Type>();
-
-            if(accepted && clazz) {
-                if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Data)>>) {
-                    Data(*clazz, any.cast<data_type>());
-                } else if constexpr(std::is_member_function_pointer_v<decltype(Data)>) {
-                    (clazz->*Data)(any.cast<data_type>());
-                } else /* if constexpr(std::is_member_object_pointer_v<decltype(Data)>) */ {
-                    clazz->*Data = any.cast<data_type>();
-                }
-            }
+    } else if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Data)>> || std::is_member_function_pointer_v<decltype(Data)>) {
+        using helper_type = meta_function_helper<std::integral_constant<decltype(Data), Data>>;
+        using data_type = std::decay_t<std::tuple_element_t<!std::is_member_function_pointer_v<decltype(Data)>, typename helper_type::args_type>>;
+        accepted = any.can_cast<data_type>() || any.convert<data_type>();
+        auto *clazz = handle.try_cast<Type>();
 
-            return accepted;
-        };
+        if(accepted && clazz) {
+            if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Data)>>) {
+                Data(*clazz, any.cast<data_type>());
+            } else if constexpr(std::is_member_function_pointer_v<decltype(Data)>) {
+                (clazz->*Data)(any.cast<data_type>());
+            }
+        }
+    } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
+        using data_type = std::decay_t<decltype(std::declval<Type>().*Data)>;
+        static_assert(std::is_invocable_v<decltype(Data), Type>);
+        accepted = any.can_cast<data_type>() || any.convert<data_type>();
+        auto *clazz = handle.try_cast<Type>();
 
-        if constexpr(std::is_function_v<std::remove_pointer_t<decltype(Data)>> || std::is_member_function_pointer_v<decltype(Data)>) {
-            using helper_type = meta_function_helper<std::integral_constant<decltype(Data), Data>>;
-            using data_type = std::tuple_element_t<!std::is_member_function_pointer_v<decltype(Data)>, typename helper_type::args_type>;
-            data_type *tag = nullptr;
-            return execute(tag);
-        } else /* if constexpr(std::is_member_object_pointer_v<decltype(Data)>) */ {
-            using data_type = std::decay_t<decltype(std::declval<Type>().*Data)>;
-            static_assert(std::is_invocable_v<decltype(Data), Type>);
-            data_type *tag = nullptr;
-            return execute(tag);
+        if(accepted && clazz) {
+            clazz->*Data = any.cast<data_type>();
         }
     } else {
         static_assert(std::is_pointer_v<decltype(Data)>);
         using data_type = std::decay_t<decltype(*Data)>;
-        const bool accepted = any.can_cast<data_type>() || any.convert<data_type>();
+        accepted = any.can_cast<data_type>() || any.convert<data_type>();
 
         if(accepted) {
             *Data = any.cast<data_type>();
         }
-
-        return accepted;
     }
+
+    return accepted;
 }
 
 

+ 21 - 1
test/entt/meta/meta.cpp

@@ -86,6 +86,9 @@ struct setter_getter_type {
     int setter(int value) { return this->value = value; }
     int getter() { return value; }
 
+    int setter_with_ref(const int &value) { return this->value = value; }
+    const int & getter_with_ref() { return value; }
+
     static int static_setter(setter_getter_type &type, int value) { return type.value = value; }
     static int static_getter(const setter_getter_type &type) { return type.value; }
 };
@@ -159,7 +162,8 @@ struct Meta: public ::testing::Test {
         entt::reflect<setter_getter_type>("setter_getter")
                 .data<&setter_getter_type::static_setter, &setter_getter_type::static_getter>("x")
                 .data<&setter_getter_type::setter, &setter_getter_type::getter>("y")
-                .data<&setter_getter_type::static_setter, &setter_getter_type::getter>("z");
+                .data<&setter_getter_type::static_setter, &setter_getter_type::getter>("z")
+                .data<&setter_getter_type::setter_with_ref, &setter_getter_type::getter_with_ref>("w");
 
         entt::reflect<an_abstract_type>("an_abstract_type", std::make_pair(properties::prop_bool, false))
                 .data<&an_abstract_type::i>("i")
@@ -960,6 +964,22 @@ TEST_F(Meta, MetaDataSetterGetterAsMemberFunctions) {
     ASSERT_EQ(data.get(instance).cast<int>(), 42);
 }
 
+TEST_F(Meta, MetaDataSetterGetterWithRefAsMemberFunctions) {
+    auto data = entt::resolve<setter_getter_type>().data("w");
+    setter_getter_type instance{};
+
+    ASSERT_TRUE(data);
+    ASSERT_NE(data, entt::meta_data{});
+    ASSERT_EQ(data.parent(), entt::resolve("setter_getter"));
+    ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_STREQ(data.name(), "w");
+    ASSERT_FALSE(data.is_const());
+    ASSERT_FALSE(data.is_static());
+    ASSERT_EQ(data.get(instance).cast<int>(), 0);
+    ASSERT_TRUE(data.set(instance, 42));
+    ASSERT_EQ(data.get(instance).cast<int>(), 42);
+}
+
 TEST_F(Meta, MetaDataSetterGetterMixed) {
     auto data = entt::resolve<setter_getter_type>().data("z");
     setter_getter_type instance{};