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

meta: meta_base is no longer static

Michele Caini 3 лет назад
Родитель
Сommit
565de36155
5 измененных файлов с 77 добавлено и 46 удалено
  1. 3 18
      src/entt/meta/factory.hpp
  2. 16 13
      src/entt/meta/meta.hpp
  3. 5 6
      src/entt/meta/node.hpp
  4. 51 0
      src/entt/meta/range.hpp
  5. 2 9
      test/entt/meta/meta_base.cpp

+ 3 - 18
src/entt/meta/factory.hpp

@@ -48,17 +48,6 @@ inline void link_type_if_required(meta_type_node *owner, const id_type id) noexc
     }
 }
 
-inline void link_base_if_required(meta_type_node *owner, meta_base_node &node) noexcept {
-    for(auto it = owner->base; it; it = it->next) {
-        if(it == &node) {
-            return;
-        }
-    }
-
-    node.next = owner->base;
-    owner->base = &node;
-}
-
 inline void link_ctor_if_required(meta_type_node *owner, meta_ctor_node &node) noexcept {
     for(auto it = owner->ctor; it; it = it->next) {
         if(it == &node) {
@@ -262,8 +251,7 @@ public:
     auto base() noexcept {
         static_assert(!std::is_same_v<Type, Base> && std::is_base_of_v<Base, Type>, "Invalid base type");
 
-        static internal::meta_base_node node{
-            nullptr,
+        owner->base[type_id<Base>().hash()] = internal::meta_base_node{
             internal::meta_node<Base>::resolve(),
             [](meta_any other) noexcept -> meta_any {
                 if(auto *ptr = other.data(); ptr) {
@@ -271,11 +259,8 @@ public:
                 }
 
                 return forward_as_meta(*static_cast<const Base *>(static_cast<const Type *>(std::as_const(other).data())));
-            }
-            // tricks clang-format
-        };
+            }};
 
-        internal::link_base_if_required(owner, node);
         return meta_factory<Type>{};
     }
 
@@ -627,12 +612,12 @@ inline void meta_reset(const id_type id) noexcept {
     for(auto **it = internal::meta_context::global(); *it; it = &(*it)->next) {
         if(auto *node = *it; node->id == id) {
             clear_chain(&node->prop);
-            clear_chain(&node->base);
             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->templ.reset();
             node->dtor = nullptr;

+ 16 - 13
src/entt/meta/meta.hpp

@@ -343,9 +343,11 @@ public:
     [[nodiscard]] const Type *try_cast() const {
         auto *self = any_cast<Type>(&storage);
 
-        for(auto *it = node ? node->base : nullptr; it && !self; it = it->next) {
-            const auto &as_const = it->cast(as_ref());
-            self = as_const.template try_cast<Type>();
+        if(!self && node) {
+            for(auto it = node->base.cbegin(), last = node->base.cend(); it != last && !self; ++it) {
+                const auto &as_const = it->second.cast(as_ref());
+                self = as_const.template try_cast<Type>();
+            }
         }
 
         return self;
@@ -356,8 +358,10 @@ public:
     [[nodiscard]] Type *try_cast() {
         auto *self = any_cast<Type>(&storage);
 
-        for(auto *it = node ? node->base : nullptr; it && !self; it = it->next) {
-            self = it->cast(as_ref()).template try_cast<Type>();
+        if(!self && node) {
+            for(auto it = node->base.cbegin(), last = node->base.cend(); it != last && !self; ++it) {
+                self = it->second.cast(as_ref()).template try_cast<Type>();
+            }
         }
 
         return self;
@@ -943,8 +947,7 @@ class meta_type {
                     if(const auto &info = other.info(); info == type.info()) {
                         ++direct;
                     } else {
-                        ext += internal::find_by<&node_type::base>(info, type.node)
-                               || type.node->conv.contains(info.hash())
+                        ext += type.node->base.contains(info.hash()) || type.node->conv.contains(info.hash())
                                || (type.node->conversion_helper && other.node->conversion_helper);
                     }
                 }
@@ -980,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 ? curr->type : nullptr} {}
+    meta_type(const base_node_type &curr) noexcept
+        : node{curr.type} {}
 
     /**
      * @brief Returns the type info object of the underlying type.
@@ -1140,8 +1143,8 @@ public:
      * @brief Returns a range to visit registered top-level base meta types.
      * @return An iterable range to visit registered top-level base meta types.
      */
-    [[nodiscard]] old_meta_range<meta_type, internal::meta_base_node> base() const noexcept {
-        return {node->base, nullptr};
+    [[nodiscard]] meta_range<meta_type, typename decltype(internal::meta_type_node::base)::const_iterator> base() const noexcept {
+        return {node->base.cbegin(), node->base.cend()};
     }
 
     /**
@@ -1402,8 +1405,8 @@ bool meta_any::set(const id_type id, Type &&value) {
             return other;
         }
 
-        for(auto *it = node->base; it; it = it->next) {
-            const auto &as_const = it->cast(as_ref());
+        for(auto &&curr: node->base) {
+            const auto &as_const = curr.second.cast(as_ref());
 
             if(auto other = as_const.allow_cast(type); other) {
                 return other;

+ 5 - 6
src/entt/meta/node.hpp

@@ -51,9 +51,8 @@ struct meta_prop_node {
 };
 
 struct meta_base_node {
-    meta_base_node *next;
-    meta_type_node *const type;
-    meta_any (*const cast)(meta_any) noexcept;
+    meta_type_node *type;
+    meta_any (*cast)(meta_any) noexcept;
 };
 
 struct meta_conv_node {
@@ -119,7 +118,7 @@ struct meta_type_node {
     meta_any (*const from_void)(void *, const void *);
     std::unique_ptr<meta_template_node> templ;
     meta_ctor_node *ctor{nullptr};
-    meta_base_node *base{nullptr};
+    dense_map<id_type, meta_base_node, identity> base{};
     dense_map<id_type, meta_conv_node, identity> conv{};
     meta_data_node *data{nullptr};
     meta_func_node *func{nullptr};
@@ -236,8 +235,8 @@ template<auto Member, typename Type>
         }
     }
 
-    for(auto *curr = node->base; curr; curr = curr->next) {
-        if(auto *ret = find_by<Member>(info_or_id, curr->type); ret) {
+    for(auto &&curr: node->base) {
+        if(auto *ret = find_by<Member>(info_or_id, curr.second.type); ret) {
             return ret;
         }
     }

+ 51 - 0
src/entt/meta/range.hpp

@@ -58,6 +58,49 @@ private:
     node_type *it;
 };
 
+template<typename Type, typename It>
+struct meta_range_iterator final {
+    using difference_type = std::ptrdiff_t;
+    using value_type = Type;
+    using pointer = input_iterator_pointer<value_type>;
+    using reference = value_type;
+    using iterator_category = std::input_iterator_tag;
+
+    meta_range_iterator() noexcept
+        : it{} {}
+
+    meta_range_iterator(It iter) noexcept
+        : it{iter} {}
+
+    meta_range_iterator &operator++() noexcept {
+        return ++it, *this;
+    }
+
+    meta_range_iterator operator++(int) noexcept {
+        meta_range_iterator orig = *this;
+        return ++(*this), orig;
+    }
+
+    [[nodiscard]] reference operator*() const noexcept {
+        return it->second;
+    }
+
+    [[nodiscard]] pointer operator->() const noexcept {
+        return operator*();
+    }
+
+    [[nodiscard]] bool operator==(const meta_range_iterator &other) const noexcept {
+        return it == other.it;
+    }
+
+    [[nodiscard]] bool operator!=(const meta_range_iterator &other) const noexcept {
+        return !(*this == other);
+    }
+
+private:
+    It it;
+};
+
 } // namespace internal
 
 /**
@@ -73,6 +116,14 @@ private:
 template<typename Type, typename Node = typename Type::node_type>
 using old_meta_range = iterable_adaptor<internal::old_meta_range_iterator<Type, Node>>;
 
+/**
+ * @brief Iterable range to use to iterate all types of meta objects.
+ * @tparam Type Type of meta objects returned.
+ * @tparam It Type of forward iterator.
+ */
+template<typename Type, typename It>
+using meta_range = iterable_adaptor<internal::meta_range_iterator<Type, It>>;
+
 } // namespace entt
 
 #endif

+ 2 - 9
test/entt/meta/meta_base.cpp

@@ -183,13 +183,6 @@ TEST_F(MetaBase, ReRegistration) {
 
     auto *node = entt::internal::meta_node<derived_t>::resolve();
 
-    ASSERT_NE(node->base, nullptr);
-    ASSERT_NE(node->base->type->base, nullptr);
-    ASSERT_EQ(node->base->type->base->next, nullptr);
-    ASSERT_EQ(node->base->type->base->type->base, nullptr);
-
-    ASSERT_NE(node->base->next, nullptr);
-    ASSERT_EQ(node->base->next->type->base, nullptr);
-
-    ASSERT_EQ(node->base->next->next, nullptr);
+    ASSERT_FALSE(node->base.empty());
+    ASSERT_EQ(node->base.size(), 2u);
 }