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

meta: meta_data::set/get accept more args than needed (and filter them)

skypjack 5 дней назад
Родитель
Сommit
2507b60dff
2 измененных файлов с 52 добавлено и 3 удалено
  1. 2 2
      src/entt/meta/meta.hpp
  2. 50 1
      test/entt/meta/meta_data.cpp

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

@@ -884,7 +884,7 @@ struct meta_data: meta_object<internal::meta_data_node> {
     template<typename Instance = meta_handle>
     // NOLINTNEXTLINE(modernize-use-nodiscard)
     bool set(Instance &&instance, auto &&...args) const {
-        return (sizeof...(args) == set_arity()) && node_or_assert().set(meta_handle{*ctx, stl::forward<Instance>(instance)}, stl::array<meta_any, sizeof...(args)>{meta_any{*ctx, stl::forward<decltype(args)>(args)}...}.data());
+        return (sizeof...(args) >= set_arity()) && node_or_assert().set(meta_handle{*ctx, stl::forward<Instance>(instance)}, stl::array<meta_any, sizeof...(args)>{meta_any{*ctx, stl::forward<decltype(args)>(args)}...}.data());
     }
 
     /**
@@ -896,7 +896,7 @@ struct meta_data: meta_object<internal::meta_data_node> {
      */
     template<typename Instance = meta_handle>
     [[nodiscard]] meta_any get(Instance &&instance, auto &&...args) const {
-        return (sizeof...(args) == get_arity()) ? node_or_assert().get(meta_handle{*ctx, stl::forward<Instance>(instance)}, stl::array<meta_any, sizeof...(args)>{meta_any{*ctx, stl::forward<decltype(args)>(args)}...}.data()) : meta_any{meta_ctx_arg, *ctx};
+        return (sizeof...(args) >= get_arity()) ? node_or_assert().get(meta_handle{*ctx, stl::forward<Instance>(instance)}, stl::array<meta_any, sizeof...(args)>{meta_any{*ctx, stl::forward<decltype(args)>(args)}...}.data()) : meta_any{meta_ctx_arg, *ctx};
     }
 
     /**

+ 50 - 1
test/entt/meta/meta_data.cpp

@@ -312,6 +312,18 @@ TEST_F(MetaData, GetInvalidArg) {
     ASSERT_FALSE(entt::resolve<clazz>().data("i"_hs).get(instance));
 }
 
+TEST_F(MetaData, GetUnnecessaryArgs) {
+    using namespace entt::literals;
+
+    entt::meta_any any{clazz{}};
+    any.cast<clazz &>().i = 3;
+    const auto value = entt::resolve<clazz>().data("i"_hs).get(any, 2, 'c');
+
+    ASSERT_TRUE(value);
+    ASSERT_TRUE(static_cast<bool>(value.cast<int>()));
+    ASSERT_EQ(value.cast<int>(), 3);
+}
+
 TEST_F(MetaData, SetMetaAnyArg) {
     using namespace entt::literals;
 
@@ -387,6 +399,17 @@ TEST_F(MetaData, SetByConstRef) {
     ASSERT_EQ(any.cast<clazz>().i, 3);
 }
 
+TEST_F(MetaData, SetUnnecessaryArgs) {
+    using namespace entt::literals;
+
+    entt::meta_any any{clazz{}};
+    const entt::meta_any value{1};
+
+    ASSERT_EQ(any.cast<clazz>().i, 0);
+    ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(any, value, 2, 'c'));
+    ASSERT_EQ(any.cast<clazz>().i, 1);
+}
+
 TEST_F(MetaData, SetterGetterAsFreeFunctions) {
     using namespace entt::literals;
 
@@ -503,7 +526,7 @@ TEST_F(MetaData, SetterGetterReadOnlyDataMember) {
     ASSERT_EQ(data.get(instance).cast<int>(), 0);
 }
 
-TEST_F(MetaData, SetterGetterMultiArg) {
+TEST_F(MetaData, SetterGetterMultiArgs) {
     using namespace entt::literals;
 
     auto data = entt::resolve<setter_getter>().data("multi"_hs);
@@ -527,6 +550,32 @@ TEST_F(MetaData, SetterGetterMultiArg) {
     ASSERT_EQ(data.get(instance, 2).cast<int>(), 2);
 }
 
+TEST_F(MetaData, SetterGetterUnnecessaryArgs) {
+    using namespace entt::literals;
+
+    auto data = entt::resolve<setter_getter>().data("y"_hs);
+    setter_getter instance{};
+
+    ASSERT_TRUE(data);
+    ASSERT_EQ(data.get(instance).cast<int>(), 0);
+    ASSERT_TRUE(data.set(instance, 1., 2, 'c'));
+    ASSERT_EQ(data.get(instance, 2, 'c').cast<int>(), 1);
+    ASSERT_TRUE(data.set(instance, 3, 2, 'c'));
+    ASSERT_EQ(data.get(instance, 2, 'c').cast<int>(), 3);
+}
+
+TEST_F(MetaData, SetterGetterMultiArgsUnnecessaryArgs) {
+    using namespace entt::literals;
+
+    auto data = entt::resolve<setter_getter>().data("multi"_hs);
+    setter_getter instance{};
+
+    ASSERT_TRUE(data);
+    ASSERT_EQ(data.get(instance, 2, 1, 'c').cast<int>(), 0);
+    ASSERT_TRUE(data.set(instance, 0, 0.5, 2.0, 1, 'c'));
+    ASSERT_EQ(data.get(instance, 2, 1, 'c').cast<int>(), 2);
+}
+
 TEST_F(MetaData, ConstInstance) {
     using namespace entt::literals;