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

meta: added meta_base to further reduce implicit hidden lookups

skypjack 1 месяц назад
Родитель
Сommit
2aecdfe497

+ 45 - 11
src/entt/meta/meta.hpp

@@ -1032,6 +1032,44 @@ private:
     const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
 };
 
+/*! @brief Opaque wrapper for base types. */
+class meta_base {
+    [[nodiscard]] auto &node_or_assert() const noexcept {
+        ENTT_ASSERT(node != nullptr, "Invalid pointer to node");
+        return *node;
+    }
+
+public:
+    /*! @brief Default constructor. */
+    meta_base() noexcept = default;
+
+    /**
+     * @brief Context aware constructor for meta objects.
+     * @param area The context from which to search for meta types.
+     * @param curr The underlying node with which to construct the instance.
+     */
+    meta_base(const meta_ctx &area, const internal::meta_base_node &curr) noexcept
+        : node{&curr},
+          ctx{&area} {}
+
+    /*! @copydoc meta_any::type */
+    [[nodiscard]] inline meta_type type() const noexcept;
+
+    /*! @copydoc meta_data::operator bool */
+    [[nodiscard]] explicit operator bool() const noexcept {
+        return (node != nullptr);
+    }
+
+    /*! @copydoc meta_data::operator== */
+    [[nodiscard]] bool operator==(const meta_base &other) const noexcept {
+        return (ctx == other.ctx) && (node == other.node);
+    }
+
+private:
+    const internal::meta_base_node *node{};
+    const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
+};
+
 /*! @brief Opaque wrapper for types. */
 class meta_type {
     [[nodiscard]] const auto &fetch_node() const {
@@ -1107,14 +1145,6 @@ public:
         : node{&curr},
           ctx{&area} {}
 
-    /**
-     * @brief Context aware constructor for meta objects.
-     * @param area The context from which to search for meta types.
-     * @param curr The underlying node with which to construct the instance.
-     */
-    meta_type(const meta_ctx &area, const internal::meta_base_node &curr) noexcept
-        : meta_type{area, curr.type(internal::meta_context::from(area))} {}
-
     /**
      * @brief Returns the type info object of the underlying type.
      * @return The type info object of the underlying type.
@@ -1307,8 +1337,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]] meta_range<meta_type, decltype(internal::meta_type_descriptor::base)::const_iterator> base() const noexcept {
-        using range_type = meta_range<meta_type, decltype(internal::meta_type_descriptor::base)::const_iterator>;
+    [[nodiscard]] meta_range<meta_base, decltype(internal::meta_type_descriptor::base)::const_iterator> base() const noexcept {
+        using range_type = meta_range<meta_base, decltype(internal::meta_type_descriptor::base)::const_iterator>;
         return fetch_node().details ? range_type{{*ctx, fetch_node().details->base.cbegin()}, {*ctx, fetch_node().details->base.cend()}} : range_type{};
     }
 
@@ -1426,7 +1456,7 @@ public:
         }
 
         for(auto &&curr: base()) {
-            if(auto elem = curr.second.invoke(id, *wrapped.operator->(), args, sz); elem) {
+            if(auto elem = curr.second.type().invoke(id, *wrapped.operator->(), args, sz); elem) {
                 return elem;
             }
         }
@@ -1604,6 +1634,10 @@ inline bool meta_any::assign(meta_any &&other) {
     return index < arity() ? node_or_assert().arg(*ctx, index) : meta_type{};
 }
 
+[[nodiscard]] inline meta_type meta_base::type() const noexcept {
+    return meta_type{*ctx, node_or_assert().type(internal::meta_context::from(*ctx))};
+}
+
 /*! @cond TURN_OFF_DOXYGEN */
 class meta_sequence_container::meta_iterator final {
     using vtable_type = void(const void *, const std::ptrdiff_t, meta_any *);

+ 21 - 0
test/entt/meta/meta_base.cpp

@@ -60,6 +60,27 @@ struct MetaBase: ::testing::Test {
     }
 };
 
+TEST_F(MetaBase, Comparison) {
+    const auto type = entt::resolve<base_3>();
+    const auto base = type.base().begin()->second;
+
+    ASSERT_TRUE(base);
+
+    ASSERT_EQ(base, base);
+    ASSERT_NE(base, entt::meta_base{});
+    ASSERT_FALSE(base != base);
+    ASSERT_TRUE(base == base);
+}
+
+TEST_F(MetaBase, Type) {
+    const auto type = entt::resolve<base_3>();
+    const auto iterable = type.base();
+
+    ASSERT_EQ(++iterable.begin(), iterable.end());
+    ASSERT_EQ(iterable.begin()->first, entt::type_id<base_2>().hash());
+    ASSERT_EQ(iterable.begin()->second.type(), entt::resolve<base_2>());
+}
+
 TEST_F(MetaBase, Base) {
     auto any = entt::resolve<derived>().construct();
     any.cast<derived &>().value_1 = 2;

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

@@ -218,7 +218,7 @@ TEST_F(MetaContext, MetaBase) {
     ASSERT_EQ((std::distance(global.base().cbegin(), global.base().cend())), 0);
     ASSERT_EQ((std::distance(local.base().cbegin(), local.base().cend())), 1);
 
-    ASSERT_EQ(local.base().cbegin()->second.info(), entt::type_id<base>());
+    ASSERT_EQ(local.base().cbegin()->second.type().info(), entt::type_id<base>());
 
     ASSERT_FALSE(entt::resolve(entt::type_id<base>()));
     ASSERT_TRUE(entt::resolve(ctx(), entt::type_id<base>()));

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

@@ -124,7 +124,7 @@ TEST_F(MetaFactory, Base) {
     ASSERT_NE(range.begin(), range.end());
     ASSERT_EQ(std::distance(range.begin(), range.end()), 1);
     ASSERT_EQ(range.begin()->first, entt::type_id<base>().hash());
-    ASSERT_EQ(range.begin()->second.info(), entt::type_id<base>());
+    ASSERT_EQ(range.begin()->second.type().info(), entt::type_id<base>());
 }
 
 TEST_F(MetaFactory, Conv) {

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

@@ -423,7 +423,7 @@ TEST_F(MetaType, Base) {
 
     for(auto curr: type.base()) {
         ASSERT_EQ(curr.first, entt::type_id<base>().hash());
-        ASSERT_EQ(curr.second, entt::resolve<base>());
+        ASSERT_EQ(curr.second.type(), entt::resolve<base>());
     }
 }