Browse Source

meta: arrays are no longer indexable via meta_type::set/get

Michele Caini 5 years ago
parent
commit
bf3864b2da
4 changed files with 29 additions and 123 deletions
  1. 20 50
      src/entt/meta/factory.hpp
  2. 2 2
      src/entt/meta/internal.hpp
  3. 2 38
      src/entt/meta/meta.hpp
  4. 5 33
      test/entt/meta/meta_data.cpp

+ 20 - 50
src/entt/meta/factory.hpp

@@ -76,59 +76,35 @@ template<typename Type, typename... Args, std::size_t... Indexes>
 
 
 
 
 template<typename Type, auto Data>
 template<typename Type, auto Data>
-[[nodiscard]] bool setter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any index, [[maybe_unused]] meta_any value) {
+[[nodiscard]] bool setter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any value) {
     bool accepted = false;
     bool accepted = false;
 
 
     if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>> || std::is_member_function_pointer_v<decltype(Data)>) {
     if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>> || std::is_member_function_pointer_v<decltype(Data)>) {
         using helper_type = meta_function_helper_t<decltype(Data)>;
         using helper_type = meta_function_helper_t<decltype(Data)>;
         using data_type = std::tuple_element_t<!std::is_member_function_pointer_v<decltype(Data)>, typename helper_type::args_type>;
         using data_type = std::tuple_element_t<!std::is_member_function_pointer_v<decltype(Data)>, typename helper_type::args_type>;
-        static_assert(std::is_invocable_v<decltype(Data), Type &, data_type>, "Invalid function or member function");
-        auto * const clazz = instance.try_cast<Type>();
-        auto * const direct = value.try_cast<data_type>();
 
 
-        if(clazz && (direct || value.convert<data_type>())) {
-            std::invoke(Data, *clazz, direct ? *direct : value.cast<data_type>());
-            accepted = true;
+        if(auto * const clazz = instance.try_cast<Type>(); clazz) {
+            if(auto * const direct = value.try_cast<data_type>(); direct || value.convert<data_type>()) {
+                std::invoke(Data, *clazz, direct ? *direct : value.cast<data_type>());
+                accepted = true;
+            }
         }
         }
     } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
     } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
         using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
         using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
-        static_assert(std::is_invocable_v<decltype(Data), Type *>, "Invalid data member");
-        auto * const clazz = instance.try_cast<Type>();
-
-        if constexpr(std::is_array_v<data_type>) {
-            using underlying_type = std::remove_extent_t<data_type>;
-            auto * const direct = value.try_cast<underlying_type>();
-            auto * const idx = index.try_cast<std::size_t>();
 
 
-            if(clazz && idx && (direct || value.convert<underlying_type>())) {
-                std::invoke(Data, clazz)[*idx] = direct ? *direct : value.cast<underlying_type>();
-                accepted = true;
-            }
-        } else {
-            auto * const direct = value.try_cast<data_type>();
-
-            if(clazz && (direct || value.convert<data_type>())) {
-                std::invoke(Data, clazz) = (direct ? *direct : value.cast<data_type>());
-                accepted = true;
+        if constexpr(!std::is_array_v<data_type>) {
+            if(auto * const clazz = instance.try_cast<Type>(); clazz) {
+                if(auto * const direct = value.try_cast<data_type>(); direct || value.convert<data_type>()) {
+                    std::invoke(Data, clazz) = (direct ? *direct : value.cast<data_type>());
+                    accepted = true;
+                }
             }
             }
         }
         }
     } else {
     } else {
-        static_assert(std::is_pointer_v<decltype(Data)>, "Invalid pointer to data type");
         using data_type = std::remove_cv_t<std::remove_reference_t<decltype(*Data)>>;
         using data_type = std::remove_cv_t<std::remove_reference_t<decltype(*Data)>>;
 
 
-        if constexpr(std::is_array_v<data_type>) {
-            using underlying_type = std::remove_extent_t<data_type>;
-            auto * const direct = value.try_cast<underlying_type>();
-            auto * const idx = index.try_cast<std::size_t>();
-
-            if(idx && (direct || value.convert<underlying_type>())) {
-                (*Data)[*idx] = (direct ? *direct : value.cast<underlying_type>());
-                accepted = true;
-            }
-        } else {
-            auto * const direct = value.try_cast<data_type>();
-
-            if(direct || value.convert<data_type>()) {
+        if constexpr(!std::is_array_v<data_type>) {
+            if(auto * const direct = value.try_cast<data_type>(); direct || value.convert<data_type>()) {
                 *Data = (direct ? *direct : value.cast<data_type>());
                 *Data = (direct ? *direct : value.cast<data_type>());
                 accepted = true;
                 accepted = true;
             }
             }
@@ -140,7 +116,7 @@ template<typename Type, auto Data>
 
 
 
 
 template<typename Type, auto Data, typename Policy>
 template<typename Type, auto Data, typename Policy>
-[[nodiscard]] meta_any getter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any index) {
+[[nodiscard]] meta_any getter([[maybe_unused]] meta_any instance) {
     auto dispatch = [](auto &&value) {
     auto dispatch = [](auto &&value) {
         if constexpr(std::is_same_v<Policy, as_void_t>) {
         if constexpr(std::is_same_v<Policy, as_void_t>) {
             return meta_any{std::in_place_type<void>, std::forward<decltype(value)>(value)};
             return meta_any{std::in_place_type<void>, std::forward<decltype(value)>(value)};
@@ -153,24 +129,18 @@ template<typename Type, auto Data, typename Policy>
     };
     };
 
 
     if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>> || std::is_member_function_pointer_v<decltype(Data)>) {
     if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>> || std::is_member_function_pointer_v<decltype(Data)>) {
-        static_assert(std::is_invocable_v<decltype(Data), Type &>, "Invalid function or member function");
         auto * const clazz = instance.try_cast<Type>();
         auto * const clazz = instance.try_cast<Type>();
         return clazz ? dispatch(std::invoke(Data, *clazz)) : meta_any{};
         return clazz ? dispatch(std::invoke(Data, *clazz)) : meta_any{};
     } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
     } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
-        using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
-        static_assert(std::is_invocable_v<decltype(Data), Type *>, "Invalid data member");
-        auto * const clazz = instance.try_cast<Type>();
-
-        if constexpr(std::is_array_v<data_type>) {
-            auto * const idx = index.try_cast<std::size_t>();
-            return (clazz && idx) ? dispatch(std::invoke(Data, clazz)[*idx]) : meta_any{};
+        if constexpr(std::is_array_v<std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>>) {
+            return meta_any{};
         } else {
         } else {
+            auto * const clazz = instance.try_cast<Type>();
             return clazz ? dispatch(std::invoke(Data, clazz)) : meta_any{};
             return clazz ? dispatch(std::invoke(Data, clazz)) : meta_any{};
         }
         }
     } else if constexpr(std::is_pointer_v<std::decay_t<decltype(Data)>>) {
     } else if constexpr(std::is_pointer_v<std::decay_t<decltype(Data)>>) {
         if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) {
         if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) {
-            auto * const idx = index.try_cast<std::size_t>();
-            return idx ? dispatch((*Data)[*idx]) : meta_any{};
+            return meta_any{};
         } else {
         } else {
             return dispatch(*Data);
             return dispatch(*Data);
         }
         }
@@ -666,7 +636,7 @@ public:
             false,
             false,
             &internal::meta_info<underlying_type>::resolve,
             &internal::meta_info<underlying_type>::resolve,
             []() -> decltype(internal::meta_data_node::set) {
             []() -> decltype(internal::meta_data_node::set) {
-                if constexpr(std::is_same_v<decltype(Setter), std::nullptr_t>  || (std::is_member_object_pointer_v<decltype(Setter)> && std::is_const_v<underlying_type>)) {
+                if constexpr(std::is_same_v<decltype(Setter), std::nullptr_t> || (std::is_member_object_pointer_v<decltype(Setter)> && std::is_const_v<underlying_type>)) {
                     return nullptr;
                     return nullptr;
                 } else {
                 } else {
                     return &internal::setter<Type, Setter>;
                     return &internal::setter<Type, Setter>;

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

@@ -77,8 +77,8 @@ struct meta_data_node {
     meta_prop_node * prop;
     meta_prop_node * prop;
     const bool is_static;
     const bool is_static;
     meta_type_node *(* const type)() ENTT_NOEXCEPT;
     meta_type_node *(* const type)() ENTT_NOEXCEPT;
-    bool(* const set)(meta_any, meta_any, meta_any);
-    meta_any(* const get)(meta_any, meta_any);
+    bool(* const set)(meta_any, meta_any);
+    meta_any(* const get)(meta_any);
 };
 };
 
 
 
 

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

@@ -711,28 +711,7 @@ struct meta_data {
      */
      */
     template<typename Type>
     template<typename Type>
     bool set(meta_handle instance, Type &&value) const {
     bool set(meta_handle instance, Type &&value) const {
-        return node->set && node->set(*instance, {}, std::forward<Type>(value));
-    }
-
-    /**
-     * @brief Sets the i-th element of a given array.
-     *
-     * It must be possible to cast the instance to the parent type of the meta
-     * data. Otherwise, invoking the setter results in an undefined
-     * behavior.<br/>
-     * The type of the value must be such that a cast or conversion to the array
-     * type is possible. Otherwise, invoking the setter does nothing.
-     *
-     * @tparam Type Type of value to assign.
-     * @param instance An opaque instance of the underlying type.
-     * @param index Position of the underlying element to set.
-     * @param value Parameter to use to set the underlying element.
-     * @return True in case of success, false otherwise.
-     */
-    template<typename Type>
-    bool set(meta_handle instance, std::size_t index, Type &&value) const {
-        ENTT_ASSERT(index < node->type()->extent);
-        return node->set && node->set(*instance, index, std::forward<Type>(value));
+        return node->set && node->set(*instance, std::forward<Type>(value));
     }
     }
 
 
     /**
     /**
@@ -745,22 +724,7 @@ struct meta_data {
      * @return A meta any containing the value of the underlying variable.
      * @return A meta any containing the value of the underlying variable.
      */
      */
     [[nodiscard]] meta_any get(meta_handle instance) const {
     [[nodiscard]] meta_any get(meta_handle instance) const {
-        return node->get(*instance, {});
-    }
-
-    /**
-     * @brief Gets the i-th element of a given array.
-     *
-     * It must be possible to cast the instance to the parent type of the meta
-     * data. Otherwise, invoking the getter results in an undefined behavior.
-     *
-     * @param instance An opaque instance of the underlying type.
-     * @param index Position of the underlying element to get.
-     * @return A meta any containing the value of the underlying element.
-     */
-    [[nodiscard]] meta_any get(meta_handle instance, std::size_t index) const {
-        ENTT_ASSERT(index < node->type()->extent);
-        return node->get(*instance, index);
+        return node->get(*instance);
     }
     }
 
 
     /*! @copydoc meta_ctor::prop */
     /*! @copydoc meta_ctor::prop */

+ 5 - 33
test/entt/meta/meta_data.cpp

@@ -54,7 +54,7 @@ struct setter_getter_t {
 
 
 struct array_t {
 struct array_t {
     static inline int global[3];
     static inline int global[3];
-    int local[3];
+    int local[5];
 };
 };
 
 
 enum class property_t {
 enum class property_t {
@@ -347,10 +347,6 @@ TEST_F(MetaData, SetterGetterReadOnlyDataMember) {
 TEST_F(MetaData, ArrayStatic) {
 TEST_F(MetaData, ArrayStatic) {
     auto data = entt::resolve<array_t>().data("global"_hs);
     auto data = entt::resolve<array_t>().data("global"_hs);
 
 
-    array_t::global[0] = 3;
-    array_t::global[1] = 5;
-    array_t::global[2] = 7;
-
     ASSERT_TRUE(data);
     ASSERT_TRUE(data);
     ASSERT_EQ(data.parent(), entt::resolve_id("array"_hs));
     ASSERT_EQ(data.parent(), entt::resolve_id("array"_hs));
     ASSERT_EQ(data.type(), entt::resolve<int[3]>());
     ASSERT_EQ(data.type(), entt::resolve<int[3]>());
@@ -359,46 +355,22 @@ TEST_F(MetaData, ArrayStatic) {
     ASSERT_TRUE(data.is_static());
     ASSERT_TRUE(data.is_static());
     ASSERT_TRUE(data.type().is_array());
     ASSERT_TRUE(data.type().is_array());
     ASSERT_EQ(data.type().extent(), 3);
     ASSERT_EQ(data.type().extent(), 3);
-    ASSERT_EQ(data.get({}, 0).cast<int>(), 3);
-    ASSERT_EQ(data.get({}, 1).cast<int>(), 5);
-    ASSERT_EQ(data.get({}, 2).cast<int>(), 7);
-    ASSERT_FALSE(data.set({}, 0, 'c'));
-    ASSERT_EQ(data.get({}, 0).cast<int>(), 3);
-    ASSERT_TRUE(data.set({}, 0, data.get({}, 0).cast<int>()+2));
-    ASSERT_TRUE(data.set({}, 1, data.get({}, 1).cast<int>()+2));
-    ASSERT_TRUE(data.set({}, 2, data.get({}, 2).cast<int>()+2));
-    ASSERT_EQ(data.get({}, 0).cast<int>(), 5);
-    ASSERT_EQ(data.get({}, 1).cast<int>(), 7);
-    ASSERT_EQ(data.get({}, 2).cast<int>(), 9);
+    ASSERT_FALSE(data.get({}));
 }
 }
 
 
 TEST_F(MetaData, Array) {
 TEST_F(MetaData, Array) {
     auto data = entt::resolve<array_t>().data("local"_hs);
     auto data = entt::resolve<array_t>().data("local"_hs);
     array_t instance;
     array_t instance;
 
 
-    instance.local[0] = 3;
-    instance.local[1] = 5;
-    instance.local[2] = 7;
-
     ASSERT_TRUE(data);
     ASSERT_TRUE(data);
     ASSERT_EQ(data.parent(), entt::resolve_id("array"_hs));
     ASSERT_EQ(data.parent(), entt::resolve_id("array"_hs));
-    ASSERT_EQ(data.type(), entt::resolve<int[3]>());
+    ASSERT_EQ(data.type(), entt::resolve<int[5]>());
     ASSERT_EQ(data.id(), "local"_hs);
     ASSERT_EQ(data.id(), "local"_hs);
     ASSERT_FALSE(data.is_const());
     ASSERT_FALSE(data.is_const());
     ASSERT_FALSE(data.is_static());
     ASSERT_FALSE(data.is_static());
     ASSERT_TRUE(data.type().is_array());
     ASSERT_TRUE(data.type().is_array());
-    ASSERT_EQ(data.type().extent(), 3);
-    ASSERT_EQ(data.get(instance, 0).cast<int>(), 3);
-    ASSERT_EQ(data.get(instance, 1).cast<int>(), 5);
-    ASSERT_EQ(data.get(instance, 2).cast<int>(), 7);
-    ASSERT_FALSE(data.set(instance, 0, 'c'));
-    ASSERT_EQ(data.get(instance, 0).cast<int>(), 3);
-    ASSERT_TRUE(data.set(instance, 0, data.get(instance, 0).cast<int>()+2));
-    ASSERT_TRUE(data.set(instance, 1, data.get(instance, 1).cast<int>()+2));
-    ASSERT_TRUE(data.set(instance, 2, data.get(instance, 2).cast<int>()+2));
-    ASSERT_EQ(data.get(instance, 0).cast<int>(), 5);
-    ASSERT_EQ(data.get(instance, 1).cast<int>(), 7);
-    ASSERT_EQ(data.get(instance, 2).cast<int>(), 9);
+    ASSERT_EQ(data.type().extent(), 5);
+    ASSERT_FALSE(data.get(instance));
 }
 }
 
 
 TEST_F(MetaData, AsVoid) {
 TEST_F(MetaData, AsVoid) {