Преглед изворни кода

meta: prepare for multi-setters on meta data members

Michele Caini пре 4 година
родитељ
комит
6b2a3b2916
5 измењених фајлова са 122 додато и 15 уклоњено
  1. 36 12
      src/entt/meta/factory.hpp
  2. 22 0
      src/entt/meta/meta.hpp
  3. 3 0
      src/entt/meta/node.hpp
  4. 23 0
      src/entt/meta/utility.hpp
  5. 38 3
      test/entt/meta/meta_data.cpp

+ 36 - 12
src/entt/meta/factory.hpp

@@ -401,8 +401,10 @@ public:
                 {},
                 nullptr,
                 nullptr,
+                1u,
                 ((std::is_same_v<Type, data_type> || std::is_const_v<data_type>) ? internal::meta_traits::IS_CONST : internal::meta_traits::IS_NONE) | internal::meta_traits::IS_STATIC,
                 internal::meta_node<std::remove_const_t<std::remove_reference_t<data_type>>>::resolve(),
+                &meta_arg<type_list<data_type>>,
                 &meta_setter<Type, Data>,
                 &meta_getter<Type, Data, Policy>
             };
@@ -436,19 +438,41 @@ public:
     auto data(const id_type id) ENTT_NOEXCEPT {
         using data_type = std::remove_reference_t<std::invoke_result_t<decltype(Getter), Type &>>;
 
-        static internal::meta_data_node node{
-            {},
-            nullptr,
-            nullptr,
-            /* this is never static */
-            ((std::is_same_v<decltype(Setter), std::nullptr_t> || (std::is_member_object_pointer_v<decltype(Setter)> && std::is_const_v<data_type>)) ? internal::meta_traits::IS_CONST : internal::meta_traits::IS_NONE),
-            internal::meta_node<std::remove_const_t<std::remove_reference_t<data_type>>>::resolve(),
-            &meta_setter<Type, Setter>,
-            &meta_getter<Type, Getter, Policy>
-        };
+        if constexpr(std::is_same_v<decltype(Setter), std::nullptr_t>) {
+            static internal::meta_data_node node{
+                {},
+                nullptr,
+                nullptr,
+                0u,
+                /* this is never static */
+                internal::meta_traits::IS_CONST,
+                internal::meta_node<std::remove_const_t<std::remove_reference_t<data_type>>>::resolve(),
+                &meta_arg<type_list<>>,
+                &meta_setter<Type, Setter>,
+                &meta_getter<Type, Getter, Policy>
+            };
+
+            link_data_if_required(id, node);
+            return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&node.prop};
+        } else {
+            using descriptor = meta_function_helper_t<Type, decltype(Setter)>;
 
-        link_data_if_required(id, node);
-        return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&node.prop};
+            static internal::meta_data_node node{
+                {},
+                nullptr,
+                nullptr,
+                1u,
+                /* this is never static */
+                (std::is_member_object_pointer_v<decltype(Setter)> && std::is_const_v<data_type>) ? internal::meta_traits::IS_CONST : internal::meta_traits::IS_NONE,
+                internal::meta_node<std::remove_const_t<std::remove_reference_t<data_type>>>::resolve(),
+                &meta_arg<type_list<type_list_element_t<descriptor::args_type::size != 1u, typename descriptor::args_type>>>,
+                &meta_setter<Type, Setter>,
+                &meta_getter<Type, Getter, Policy>
+            };
+
+            link_data_if_required(id, node);
+            return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&node.prop};
+        }
     }
 
     /**

+ 22 - 0
src/entt/meta/meta.hpp

@@ -728,6 +728,8 @@ private:
 struct meta_data {
     /*! @brief Node type. */
     using node_type = internal::meta_data_node;
+    /*! @brief Unsigned integer type. */
+    using size_type = typename node_type::size_type;
 
     /*! @copydoc meta_prop::meta_prop */
     meta_data(const node_type *curr = nullptr) ENTT_NOEXCEPT
@@ -739,6 +741,14 @@ struct meta_data {
         return node->id;
     }
 
+    /**
+     * @brief Returns the number of setters available.
+     * @return The number of arguments accepted by the member function.
+     */
+    [[nodiscard]] size_type arity() const ENTT_NOEXCEPT {
+        return node->arity;
+    }
+
     /**
      * @brief Indicates whether a data member is constant or not.
      * @return True if the data member is constant, false otherwise.
@@ -790,6 +800,13 @@ struct meta_data {
         return node->get(std::move(instance));
     }
 
+    /**
+     * @brief Returns the type accepted by the i-th setter.
+     * @param index Index of the setter of which to return the accepted type.
+     * @return The type accepted by the i-th setter.
+     */
+    [[nodiscard]] inline meta_type arg(const size_type index) const ENTT_NOEXCEPT;
+
     /**
      * @brief Returns a range to visit registered meta properties.
      * @return An iterable range to visit registered meta properties.
@@ -1407,6 +1424,11 @@ bool meta_any::set(const id_type id, Type &&value) {
 }
 
 
+[[nodiscard]] inline meta_type meta_data::arg(const size_type index) const ENTT_NOEXCEPT {
+    return index < arity() ? node->arg(index) : meta_type{};
+}
+
+
 [[nodiscard]] inline meta_type meta_func::arg(const size_type index) const ENTT_NOEXCEPT {
     return index < arity() ? node->arg(index) : meta_type{};
 }

+ 3 - 0
src/entt/meta/node.hpp

@@ -81,11 +81,14 @@ struct meta_ctor_node {
 
 
 struct meta_data_node {
+    using size_type = std::size_t;
     id_type id;
     meta_data_node * next;
     meta_prop_node * prop;
+    const size_type arity;
     const meta_traits traits;
     meta_type_node * const type;
+    meta_type(* const arg)(const size_type) ENTT_NOEXCEPT;
     bool(* const set)(meta_handle, meta_any);
     meta_any(* const get)(meta_handle);
 };

+ 23 - 0
src/entt/meta/utility.hpp

@@ -63,6 +63,26 @@ struct meta_function_descriptor<Type, Ret(Class:: *)(Args...)> {
 };
 
 
+/**
+ * @brief Meta function descriptor.
+ * @tparam Type Reflected type to which the meta data is associated.
+ * @tparam Class Actual owner of the data member.
+ * @tparam Ret Data member type.
+ */
+template<typename Type, typename Ret, typename Class>
+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>>;
+
+    /*! @brief True if the meta data is const, false otherwise. */
+    static constexpr auto is_const = false;
+    /*! @brief True if the meta data is static, false otherwise. */
+    static constexpr auto is_static = false;
+};
+
+
 /**
  * @brief Meta function descriptor.
  * @tparam Type Reflected type to which the meta function is associated.
@@ -100,6 +120,9 @@ class meta_function_helper {
     template<typename Ret, typename... Args, typename Class>
     static constexpr meta_function_descriptor<Type, Ret(Class:: *)(Args...)> get_rid_of_noexcept(Ret(Class:: *)(Args...));
 
+    template<typename Ret, typename Class>
+    static constexpr meta_function_descriptor<Type, Ret Class:: *> get_rid_of_noexcept(Ret Class:: *);
+
     template<typename Ret, typename... Args>
     static constexpr meta_function_descriptor<Type, Ret(*)(Args...)> get_rid_of_noexcept(Ret(*)(Args...));
 

+ 38 - 3
test/entt/meta/meta_data.cpp

@@ -38,7 +38,7 @@ struct clazz_t {
 struct setter_getter_t {
     setter_getter_t(): value{0} {}
 
-    int setter(int val) {
+    int setter(double val) {
         return value = val;
     }
 
@@ -132,7 +132,9 @@ TEST_F(MetaData, Functionalities) {
     clazz_t instance{};
 
     ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 1u);
     ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.arg(0u), entt::resolve<int>());
     ASSERT_EQ(data.id(), "i"_hs);
     ASSERT_FALSE(data.is_const());
     ASSERT_FALSE(data.is_static());
@@ -162,7 +164,9 @@ TEST_F(MetaData, Const) {
     clazz_t instance{};
 
     ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 1u);
     ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.arg(0u), entt::resolve<int>());
     ASSERT_EQ(data.id(), "j"_hs);
     ASSERT_TRUE(data.is_const());
     ASSERT_FALSE(data.is_static());
@@ -191,7 +195,9 @@ TEST_F(MetaData, Static) {
     auto data = entt::resolve<clazz_t>().data("h"_hs);
 
     ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 1u);
     ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.arg(0u), entt::resolve<int>());
     ASSERT_EQ(data.id(), "h"_hs);
     ASSERT_FALSE(data.is_const());
     ASSERT_TRUE(data.is_static());
@@ -220,7 +226,9 @@ TEST_F(MetaData, ConstStatic) {
     auto data = entt::resolve<clazz_t>().data("k"_hs);
 
     ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 1u);
     ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.arg(0u), entt::resolve<int>());
     ASSERT_EQ(data.id(), "k"_hs);
     ASSERT_TRUE(data.is_const());
     ASSERT_TRUE(data.is_static());
@@ -341,7 +349,9 @@ TEST_F(MetaData, SetterGetterAsFreeFunctions) {
     setter_getter_t instance{};
 
     ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 1u);
     ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.arg(0u), entt::resolve<int>());
     ASSERT_EQ(data.id(), "x"_hs);
     ASSERT_FALSE(data.is_const());
     ASSERT_FALSE(data.is_static());
@@ -357,13 +367,17 @@ TEST_F(MetaData, SetterGetterAsMemberFunctions) {
     setter_getter_t instance{};
 
     ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 1u);
     ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.arg(0u), entt::resolve<double>());
     ASSERT_EQ(data.id(), "y"_hs);
     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_TRUE(data.set(instance, 42.));
     ASSERT_EQ(data.get(instance).cast<int>(), 42);
+    ASSERT_TRUE(data.set(instance, 3));
+    ASSERT_EQ(data.get(instance).cast<int>(), 3);
 }
 
 TEST_F(MetaData, SetterGetterWithRefAsMemberFunctions) {
@@ -373,7 +387,9 @@ TEST_F(MetaData, SetterGetterWithRefAsMemberFunctions) {
     setter_getter_t instance{};
 
     ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 1u);
     ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.arg(0u), entt::resolve<int>());
     ASSERT_EQ(data.id(), "w"_hs);
     ASSERT_FALSE(data.is_const());
     ASSERT_FALSE(data.is_static());
@@ -389,7 +405,9 @@ TEST_F(MetaData, SetterGetterMixed) {
     setter_getter_t instance{};
 
     ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 1u);
     ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.arg(0u), entt::resolve<int>());
     ASSERT_EQ(data.id(), "z"_hs);
     ASSERT_FALSE(data.is_const());
     ASSERT_FALSE(data.is_static());
@@ -405,7 +423,9 @@ TEST_F(MetaData, SetterGetterReadOnly) {
     setter_getter_t instance{};
 
     ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 0u);
     ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.arg(0u), entt::meta_type{});
     ASSERT_EQ(data.id(), "z_ro"_hs);
     ASSERT_TRUE(data.is_const());
     ASSERT_FALSE(data.is_static());
@@ -421,7 +441,9 @@ TEST_F(MetaData, SetterGetterReadOnlyDataMember) {
     setter_getter_t instance{};
 
     ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 0u);
     ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.arg(0u), entt::meta_type{});
     ASSERT_EQ(data.id(), "value"_hs);
     ASSERT_TRUE(data.is_const());
     ASSERT_FALSE(data.is_static());
@@ -463,7 +485,9 @@ TEST_F(MetaData, ArrayStatic) {
     auto data = entt::resolve<array_t>().data("global"_hs);
 
     ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 1u);
     ASSERT_EQ(data.type(), entt::resolve<int[3]>());
+    ASSERT_EQ(data.arg(0u), entt::resolve<int[3]>());
     ASSERT_EQ(data.id(), "global"_hs);
     ASSERT_FALSE(data.is_const());
     ASSERT_TRUE(data.is_static());
@@ -478,7 +502,9 @@ TEST_F(MetaData, Array) {
     array_t instance{};
 
     ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 1u);
     ASSERT_EQ(data.type(), entt::resolve<int[5]>());
+    ASSERT_EQ(data.arg(0u), entt::resolve<int[5]>());
     ASSERT_EQ(data.id(), "local"_hs);
     ASSERT_FALSE(data.is_const());
     ASSERT_FALSE(data.is_static());
@@ -492,6 +518,10 @@ TEST_F(MetaData, AsVoid) {
     auto data = entt::resolve<clazz_t>().data("void"_hs);
     clazz_t instance{};
 
+    ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 1u);
+    ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.arg(0u), entt::resolve<int>());
     ASSERT_TRUE(data.set(instance, 42));
     ASSERT_EQ(instance.i, 42);
     ASSERT_EQ(data.get(instance), entt::meta_any{std::in_place_type<void>});
@@ -503,8 +533,11 @@ TEST_F(MetaData, AsRef) {
     clazz_t instance{};
     auto data = entt::resolve<clazz_t>().data("i"_hs);
 
-    ASSERT_EQ(instance.i, 0);
+    ASSERT_TRUE(data);
+    ASSERT_EQ(data.arity(), 1u);
     ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.arg(0u), entt::resolve<int>());
+    ASSERT_EQ(instance.i, 0);
 
     data.get(instance).cast<int &>() = 3;
 
@@ -518,7 +551,9 @@ TEST_F(MetaData, AsConstRef) {
     auto data = entt::resolve<clazz_t>().data("ci"_hs);
 
     ASSERT_EQ(instance.i, 0);
+    ASSERT_EQ(data.arity(), 1u);
     ASSERT_EQ(data.type(), entt::resolve<int>());
+    ASSERT_EQ(data.arg(0u), entt::resolve<int>());
     ASSERT_DEATH(data.get(instance).cast<int &>() = 3, "");
     ASSERT_EQ(data.get(instance).cast<const int &>(), 0);
     ASSERT_EQ(data.get(instance).cast<int>(), 0);