Browse Source

meta: allow read-only data registration in meta (close #496)

Michele Caini 5 years ago
parent
commit
52faa1bec5
2 changed files with 41 additions and 3 deletions
  1. 8 2
      src/entt/meta/factory.hpp
  2. 33 1
      test/entt/meta/meta.cpp

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

@@ -705,7 +705,6 @@ public:
     template<auto Setter, auto Getter, typename Policy = as_is_t>
     auto data(const id_type id) ENTT_NOEXCEPT {
         using underlying_type = std::invoke_result_t<decltype(Getter), Type &>;
-        static_assert(std::is_invocable_v<decltype(Setter), Type &, underlying_type>, "Invalid setter and/or getter");
         auto * const type = internal::meta_info<Type>::resolve();
 
         static internal::meta_data_node node{
@@ -715,7 +714,14 @@ public:
             nullptr,
             false,
             &internal::meta_info<underlying_type>::resolve,
-            &internal::setter<Type, Setter>,
+            []() -> decltype(internal::meta_data_node::set) {
+                if constexpr(Setter == nullptr) {
+                    return Setter;
+                } else {
+                    static_assert(std::is_invocable_v<decltype(Setter), Type &, underlying_type>, "Invalid setter");
+                    return &internal::setter<Type, Setter>;
+                }
+            }(),
             &internal::getter<Type, Getter, Policy>
         };
 

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

@@ -241,7 +241,9 @@ struct Meta: ::testing::Test {
                 .data<&setter_getter_type::static_setter, &setter_getter_type::static_getter>("x"_hs)
                 .data<&setter_getter_type::setter, &setter_getter_type::getter>("y"_hs)
                 .data<&setter_getter_type::static_setter, &setter_getter_type::getter>("z"_hs)
-                .data<&setter_getter_type::setter_with_ref, &setter_getter_type::getter_with_ref>("w"_hs);
+                .data<&setter_getter_type::setter_with_ref, &setter_getter_type::getter_with_ref>("w"_hs)
+                .data<nullptr, &setter_getter_type::getter>("z_ro"_hs)
+                .data<nullptr, &setter_getter_type::value>("value"_hs);
 
         entt::meta<an_abstract_type>()
                 .type("an_abstract_type"_hs)
@@ -1257,6 +1259,36 @@ TEST_F(Meta, MetaDataSetterGetterMixed) {
     ASSERT_EQ(data.get(instance).cast<int>(), 42);
 }
 
+TEST_F(Meta, MetaDataSetterGetterReadOnly) {
+    auto data = entt::resolve<setter_getter_type>().data("z_ro"_hs);
+    setter_getter_type instance{};
+
+    ASSERT_TRUE(data);
+    ASSERT_EQ(data.parent(), entt::resolve_id("setter_getter"_hs));
+    ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.id(), "z_ro"_hs);
+    ASSERT_TRUE(data.is_const());
+    ASSERT_FALSE(data.is_static());
+    ASSERT_EQ(data.get(instance).cast<int>(), 0);
+    ASSERT_FALSE(data.set(instance, 42));
+    ASSERT_EQ(data.get(instance).cast<int>(), 0);
+}
+
+TEST_F(Meta, MetaDataSetterGetterReadOnlyDataMember) {
+    auto data = entt::resolve<setter_getter_type>().data("value"_hs);
+    setter_getter_type instance{};
+
+    ASSERT_TRUE(data);
+    ASSERT_EQ(data.parent(), entt::resolve_id("setter_getter"_hs));
+    ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.id(), "value"_hs);
+    ASSERT_TRUE(data.is_const());
+    ASSERT_FALSE(data.is_static());
+    ASSERT_EQ(data.get(instance).cast<int>(), 0);
+    ASSERT_FALSE(data.set(instance, 42));
+    ASSERT_EQ(data.get(instance).cast<int>(), 0);
+}
+
 TEST_F(Meta, MetaDataArrayStatic) {
     auto data = entt::resolve<array_type>().data("global"_hs);