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

meta: meta_data_node is no longer static

Michele Caini 3 лет назад
Родитель
Сommit
3062114f0c
5 измененных файлов с 55 добавлено и 79 удалено
  1. 21 51
      src/entt/meta/factory.hpp
  2. 15 5
      src/entt/meta/meta.hpp
  3. 7 8
      src/entt/meta/node.hpp
  4. 1 1
      src/entt/meta/range.hpp
  5. 11 14
      test/entt/meta/meta_data.cpp

+ 21 - 51
src/entt/meta/factory.hpp

@@ -59,16 +59,6 @@ inline void link_ctor_if_required(meta_type_node *owner, meta_ctor_node &node) n
     owner->ctor = &node;
 }
 
-inline void link_data_if_required(meta_type_node *owner, const id_type id, meta_data_node &node) noexcept {
-    ENTT_ASSERT((node.id = {}, !meta_type{owner}.data(id)), "Duplicate identifier");
-    node.id = id;
-
-    if(!meta_type{owner}.data(id)) {
-        node.next = owner->data;
-        owner->data = &node;
-    }
-}
-
 inline void link_func_if_required(meta_type_node *owner, const id_type id, meta_func_node &node) noexcept {
     node.id = id;
 
@@ -206,22 +196,18 @@ class meta_factory<Type> {
         using args_type = type_list<typename meta_function_helper_t<Type, decltype(value_list_element_v<Index, Setter>)>::args_type...>;
         static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
 
-        static internal::meta_data_node node{
-            {},
+        owner->data[id] = internal::meta_data_node{
+            id,
             /* this is never static */
             (std::is_member_object_pointer_v<decltype(value_list_element_v<Index, Setter>)> && ... && std::is_const_v<std::remove_reference_t<data_type>>) ? internal::meta_traits::is_const : internal::meta_traits::is_none,
             nullptr,
-            nullptr,
             Setter::size,
             internal::meta_node<std::remove_cv_t<std::remove_reference_t<data_type>>>::resolve(),
             &meta_arg<type_list<type_list_element_t<type_list_element_t<Index, args_type>::size != 1u, type_list_element_t<Index, args_type>>...>>,
             [](meta_handle instance, meta_any value) -> bool { return (meta_setter<Type, value_list_element_v<Index, Setter>>(*instance.operator->(), value.as_ref()) || ...); },
-            &meta_getter<Type, Getter, Policy>
-            // tricks clang-format
-        };
+            &meta_getter<Type, Getter, Policy>};
 
-        internal::link_data_if_required(owner, id, node);
-        return meta_factory<Type, Setter, std::integral_constant<decltype(Getter), Getter>>{&node.prop};
+        return meta_factory<Type, Setter, std::integral_constant<decltype(Getter), Getter>>{&owner->data[id].prop};
     }
 
 public:
@@ -409,40 +395,32 @@ public:
         if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
             using data_type = std::remove_reference_t<std::invoke_result_t<decltype(Data), Type &>>;
 
-            static internal::meta_data_node node{
-                {},
+            owner->data[id] = internal::meta_data_node{
+                id,
                 /* this is never static */
                 std::is_const_v<data_type> ? internal::meta_traits::is_const : internal::meta_traits::is_none,
                 nullptr,
-                nullptr,
                 1u,
                 internal::meta_node<std::remove_const_t<data_type>>::resolve(),
                 &meta_arg<type_list<std::remove_const_t<data_type>>>,
                 &meta_setter<Type, Data>,
-                &meta_getter<Type, Data, Policy>
-                // tricks clang-format
-            };
+                &meta_getter<Type, Data, Policy>};
 
-            internal::link_data_if_required(owner, id, node);
-            return meta_factory<Type, std::integral_constant<decltype(Data), Data>, std::integral_constant<decltype(Data), Data>>{&node.prop};
+            return meta_factory<Type, std::integral_constant<decltype(Data), Data>, std::integral_constant<decltype(Data), Data>>{&owner->data[id].prop};
         } else {
             using data_type = std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>;
 
-            static internal::meta_data_node node{
-                {},
+            owner->data[id] = internal::meta_data_node{
+                id,
                 ((std::is_same_v<Type, std::remove_const_t<data_type>> || std::is_const_v<data_type>) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static,
                 nullptr,
-                nullptr,
                 1u,
                 internal::meta_node<std::remove_const_t<data_type>>::resolve(),
                 &meta_arg<type_list<std::remove_const_t<data_type>>>,
                 &meta_setter<Type, Data>,
-                &meta_getter<Type, Data, Policy>
-                // tricks clang-format
-            };
+                &meta_getter<Type, Data, Policy>};
 
-            internal::link_data_if_required(owner, id, node);
-            return meta_factory<Type, std::integral_constant<decltype(Data), Data>>{&node.prop};
+            return meta_factory<Type, std::integral_constant<decltype(Data), Data>>{&owner->data[id].prop};
         }
     }
 
@@ -472,41 +450,33 @@ public:
         static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
 
         if constexpr(std::is_same_v<decltype(Setter), std::nullptr_t>) {
-            static internal::meta_data_node node{
-                {},
+            owner->data[id] = internal::meta_data_node{
+                id,
                 /* this is never static */
                 internal::meta_traits::is_const,
                 nullptr,
-                nullptr,
                 0u,
                 internal::meta_node<std::remove_cv_t<std::remove_reference_t<data_type>>>::resolve(),
                 &meta_arg<type_list<>>,
                 &meta_setter<Type, Setter>,
-                &meta_getter<Type, Getter, Policy>
-                // tricks clang-format
-            };
+                &meta_getter<Type, Getter, Policy>};
 
-            internal::link_data_if_required(owner, id, node);
-            return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&node.prop};
+            return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&owner->data[id].prop};
         } else {
             using args_type = typename meta_function_helper_t<Type, decltype(Setter)>::args_type;
 
-            static internal::meta_data_node node{
-                {},
+            owner->data[id] = internal::meta_data_node{
+                id,
                 /* this is never static nor const */
                 internal::meta_traits::is_none,
                 nullptr,
-                nullptr,
                 1u,
                 internal::meta_node<std::remove_cv_t<std::remove_reference_t<data_type>>>::resolve(),
                 &meta_arg<type_list<type_list_element_t<args_type::size != 1u, args_type>>>,
                 &meta_setter<Type, Setter>,
-                &meta_getter<Type, Getter, Policy>
-                // tricks clang-format
-            };
+                &meta_getter<Type, Getter, Policy>};
 
-            internal::link_data_if_required(owner, id, node);
-            return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&node.prop};
+            return meta_factory<Type, std::integral_constant<decltype(Setter), Setter>, std::integral_constant<decltype(Getter), Getter>>{&owner->data[id].prop};
         }
     }
 
@@ -613,12 +583,12 @@ inline void meta_reset(const id_type id) noexcept {
         if(auto *node = *it; node->id == id) {
             clear_chain(&node->prop);
             clear_chain(&node->ctor);
-            clear_chain(&node->data, &internal::meta_data_node::prop);
             clear_chain(&node->func, &internal::meta_func_node::prop);
 
             node->id = {};
             node->base.clear();
             node->conv.clear();
+            node->data.clear();
             node->dtor.dtor = nullptr;
             *it = std::exchange(node->next, nullptr);
 

+ 15 - 5
src/entt/meta/meta.hpp

@@ -983,8 +983,8 @@ public:
      * @brief Constructs an instance from a given base node.
      * @param curr The base node with which to construct the instance.
      */
-    meta_type(const base_node_type &curr) noexcept
-        : node{curr.type} {}
+    meta_type(const base_node_type *curr) noexcept
+        : node{curr ? curr->type : nullptr} {}
 
     /**
      * @brief Returns the type info object of the underlying type.
@@ -1151,8 +1151,8 @@ public:
      * @brief Returns a range to visit registered top-level meta data.
      * @return An iterable range to visit registered top-level meta data.
      */
-    [[nodiscard]] old_meta_range<meta_data> data() const noexcept {
-        return {node->data, nullptr};
+    [[nodiscard]] meta_range<meta_data, typename decltype(internal::meta_type_node::data)::const_iterator> data() const noexcept {
+        return {node->data.cbegin(), node->data.cend()};
     }
 
     /**
@@ -1164,7 +1164,17 @@ public:
      * @return The registered meta data for the given identifier, if any.
      */
     [[nodiscard]] meta_data data(const id_type id) const {
-        return internal::find_by<&node_type::data>(id, node);
+        if(auto it = node->data.find(id); it != node->data.cend()) {
+            return &it->second;
+        }
+
+        for(auto &&curr: base()) {
+            if(auto &&elem = curr.data(id); elem) {
+                return elem;
+            }
+        }
+
+        return meta_data{};
     }
 
     /**

+ 7 - 8
src/entt/meta/node.hpp

@@ -76,14 +76,13 @@ struct meta_data_node {
     using size_type = std::size_t;
 
     id_type id;
-    const meta_traits traits;
-    meta_data_node *next;
+    meta_traits traits;
     meta_prop_node *prop;
-    const size_type arity;
-    meta_type_node *const type;
-    meta_type (*const arg)(const size_type) noexcept;
-    bool (*const set)(meta_handle, meta_any);
-    meta_any (*const get)(meta_handle);
+    size_type arity;
+    meta_type_node *type;
+    meta_type (*arg)(const size_type) noexcept;
+    bool (*set)(meta_handle, meta_any);
+    meta_any (*get)(meta_handle);
 };
 
 struct meta_func_node {
@@ -124,7 +123,7 @@ struct meta_type_node {
     meta_ctor_node *ctor{nullptr};
     dense_map<id_type, meta_base_node, identity> base{};
     dense_map<id_type, meta_conv_node, identity> conv{};
-    meta_data_node *data{nullptr};
+    dense_map<id_type, meta_data_node, identity> data{};
     meta_func_node *func{nullptr};
     meta_dtor_node dtor{};
 };

+ 1 - 1
src/entt/meta/range.hpp

@@ -82,7 +82,7 @@ struct meta_range_iterator final {
     }
 
     [[nodiscard]] reference operator*() const noexcept {
-        return it->second;
+        return &it->second;
     }
 
     [[nodiscard]] pointer operator->() const noexcept {

+ 11 - 14
test/entt/meta/meta_data.cpp

@@ -663,31 +663,28 @@ TEST_F(MetaData, ReRegistration) {
     auto *node = entt::internal::meta_node<base_t>::resolve();
     auto type = entt::resolve<base_t>();
 
-    ASSERT_NE(node->data, nullptr);
-    ASSERT_EQ(node->data->next, nullptr);
+    ASSERT_FALSE(node->data.empty());
+    ASSERT_EQ(node->data.size(), 1u);
     ASSERT_TRUE(type.data("value"_hs));
 
     entt::meta<base_t>().data<&base_t::value>("field"_hs);
 
-    ASSERT_NE(node->data, nullptr);
-    ASSERT_EQ(node->data->next, nullptr);
-    ASSERT_FALSE(type.data("value"_hs));
+    ASSERT_EQ(node->data.size(), 2u);
+    ASSERT_TRUE(type.data("value"_hs));
     ASSERT_TRUE(type.data("field"_hs));
 }
 
-TEST_F(MetaData, NameCollision) {
+TEST_F(MetaData, CollisionAndReuse) {
     using namespace entt::literals;
 
-    ASSERT_NO_FATAL_FAILURE(entt::meta<clazz_t>().data<&clazz_t::j>("j"_hs));
     ASSERT_TRUE(entt::resolve<clazz_t>().data("j"_hs));
+    ASSERT_FALSE(entt::resolve<clazz_t>().data("cj"_hs));
+    ASSERT_TRUE(entt::resolve<clazz_t>().data("j"_hs).is_const());
 
+    ASSERT_NO_FATAL_FAILURE(entt::meta<clazz_t>().data<&clazz_t::i>("j"_hs));
     ASSERT_NO_FATAL_FAILURE(entt::meta<clazz_t>().data<&clazz_t::j>("cj"_hs));
-    ASSERT_FALSE(entt::resolve<clazz_t>().data("j"_hs));
-    ASSERT_TRUE(entt::resolve<clazz_t>().data("cj"_hs));
-}
 
-ENTT_DEBUG_TEST_F(MetaDataDeathTest, NameCollision) {
-    using namespace entt::literals;
-
-    ASSERT_DEATH(entt::meta<clazz_t>().data<&clazz_t::j>("i"_hs), "");
+    ASSERT_TRUE(entt::resolve<clazz_t>().data("j"_hs));
+    ASSERT_TRUE(entt::resolve<clazz_t>().data("cj"_hs));
+    ASSERT_FALSE(entt::resolve<clazz_t>().data("j"_hs).is_const());
 }