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

meta: make meta_type return the underlying context

Michele Caini 1 год назад
Родитель
Сommit
f30ca72c69
3 измененных файлов с 41 добавлено и 28 удалено
  1. 1 0
      TODO
  2. 27 28
      src/entt/meta/meta.hpp
  3. 13 0
      test/entt/meta/meta_type.cpp

+ 1 - 0
TODO

@@ -40,3 +40,4 @@ TODO:
 * allow passing arguments to meta setter/getter (we can fallback on meta invoke for everything probably)
 * delegate/sigh: forward connect/disconnect from & to *
 * a few more tests on the improved shrink_to_fit for sparse arrays
+* remove ctx from meta_any (get it from meta_type)

+ 27 - 28
src/entt/meta/meta.hpp

@@ -1095,7 +1095,7 @@ private:
 }
 
 /*! @brief Opaque wrapper for types. */
-class meta_type {
+class meta_type: public meta_basic_object {
     template<typename Func>
     [[nodiscard]] auto lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, [[maybe_unused]] bool constness, Func next) const {
         decltype(next()) candidate = nullptr;
@@ -1115,7 +1115,7 @@ class meta_type {
 
                 // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span)
                 for(; pos < sz && args[pos]; ++pos) {
-                    const auto other = curr->arg(*ctx, pos);
+                    const auto other = curr->arg(context(), pos);
                     const auto type = args[pos].type();
 
                     if(const auto &info = other.info(); info == type.info()) {
@@ -1162,8 +1162,8 @@ public:
      * @param curr The underlying node with which to construct the instance.
      */
     meta_type(const meta_ctx &area, internal::meta_type_node curr) noexcept
-        : node{std::move(curr)},
-          ctx{&area} {}
+        : meta_basic_object{area},
+          node{std::move(curr)} {}
 
     /**
      * @brief Context aware constructor for meta objects.
@@ -1260,7 +1260,7 @@ public:
      * doesn't refer to a pointer type.
      */
     [[nodiscard]] meta_type remove_pointer() const noexcept {
-        return (node.remove_pointer != nullptr) ? meta_type{*ctx, node.remove_pointer(internal::meta_context::from(*ctx))} : *this;
+        return (node.remove_pointer != nullptr) ? meta_type{context(), node.remove_pointer(internal::meta_context::from(context()))} : *this;
     }
 
     /**
@@ -1310,7 +1310,7 @@ public:
      * @return The tag for the class template of the underlying type.
      */
     [[nodiscard]] meta_type template_type() const noexcept {
-        return (node.templ.resolve != nullptr) ? meta_type{*ctx, node.templ.resolve(internal::meta_context::from(*ctx))} : meta_type{};
+        return (node.templ.resolve != nullptr) ? meta_type{context(), node.templ.resolve(internal::meta_context::from(context()))} : meta_type{};
     }
 
     /**
@@ -1319,7 +1319,7 @@ public:
      * @return The type of the i-th template argument of a type.
      */
     [[nodiscard]] meta_type template_arg(const size_type index) const noexcept {
-        return index < template_arity() ? meta_type{*ctx, node.templ.arg(internal::meta_context::from(*ctx), index)} : meta_type{};
+        return index < template_arity() ? meta_type{context(), node.templ.arg(internal::meta_context::from(context()), index)} : meta_type{};
     }
 
     /**
@@ -1329,7 +1329,7 @@ public:
      */
     [[nodiscard]] bool can_cast(const meta_type &other) const noexcept {
         // casting this is UB in all cases but we aren't going to use the resulting pointer, so...
-        return other && (internal::try_cast(internal::meta_context::from(*ctx), node, *other.node.info, this) != nullptr);
+        return other && (internal::try_cast(internal::meta_context::from(context()), node, *other.node.info, this) != nullptr);
     }
 
     /**
@@ -1338,7 +1338,7 @@ public:
      * @return True if the conversion is allowed, false otherwise.
      */
     [[nodiscard]] bool can_convert(const meta_type &other) const noexcept {
-        return (internal::try_convert(internal::meta_context::from(*ctx), node, other.info(), other.is_arithmetic() || other.is_enum(), nullptr, [](const void *, auto &&...args) { return ((static_cast<void>(args), 1) + ... + 0u); }) != 0u);
+        return (internal::try_convert(internal::meta_context::from(context()), node, other.info(), other.is_arithmetic() || other.is_enum(), nullptr, [](const void *, auto &&...args) { return ((static_cast<void>(args), 1) + ... + 0u); }) != 0u);
     }
 
     /**
@@ -1347,7 +1347,7 @@ public:
      */
     [[nodiscard]] meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator> base() const noexcept {
         using range_type = meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator>;
-        return node.details ? range_type{{*ctx, node.details->base.cbegin()}, {*ctx, node.details->base.cend()}} : range_type{};
+        return node.details ? range_type{{context(), node.details->base.cbegin()}, {context(), node.details->base.cend()}} : range_type{};
     }
 
     /**
@@ -1356,7 +1356,7 @@ public:
      */
     [[nodiscard]] meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator> data() const noexcept {
         using range_type = meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator>;
-        return node.details ? range_type{{*ctx, node.details->data.cbegin()}, {*ctx, node.details->data.cend()}} : range_type{};
+        return node.details ? range_type{{context(), node.details->data.cbegin()}, {context(), node.details->data.cend()}} : range_type{};
     }
 
     /**
@@ -1365,8 +1365,8 @@ public:
      * @return The registered meta data for the given identifier, if any.
      */
     [[nodiscard]] meta_data data(const id_type id) const {
-        const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), node, id);
-        return (elem != nullptr) ? meta_data{*ctx, *elem} : meta_data{};
+        const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(context()), node, id);
+        return (elem != nullptr) ? meta_data{context(), *elem} : meta_data{};
     }
 
     /**
@@ -1375,7 +1375,7 @@ public:
      */
     [[nodiscard]] meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator> func() const noexcept {
         using return_type = meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator>;
-        return node.details ? return_type{{*ctx, node.details->func.cbegin()}, {*ctx, node.details->func.cend()}} : return_type{};
+        return node.details ? return_type{{context(), node.details->func.cbegin()}, {context(), node.details->func.cend()}} : return_type{};
     }
 
     /**
@@ -1384,8 +1384,8 @@ public:
      * @return The registered meta function for the given identifier, if any.
      */
     [[nodiscard]] meta_func func(const id_type id) const {
-        const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node, id);
-        return (elem != nullptr) ? meta_func{*ctx, *elem} : meta_func{};
+        const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(context()), node, id);
+        return (elem != nullptr) ? meta_func{context(), *elem} : meta_func{};
     }
 
     /**
@@ -1397,15 +1397,15 @@ public:
     [[nodiscard]] meta_any construct(meta_any *const args, const size_type sz) const {
         if(node.details) {
             if(const auto *candidate = lookup(args, sz, false, [first = node.details->ctor.cbegin(), last = node.details->ctor.cend()]() mutable { return first == last ? nullptr : &*(first++); }); candidate) {
-                return candidate->invoke(*ctx, args);
+                return candidate->invoke(context(), args);
             }
         }
 
         if(sz == 0u && (node.default_constructor != nullptr)) {
-            return node.default_constructor(*ctx);
+            return node.default_constructor(context());
         }
 
-        return meta_any{meta_ctx_arg, *ctx};
+        return meta_any{meta_ctx_arg, context()};
     }
 
     /**
@@ -1416,7 +1416,7 @@ public:
      */
     template<typename... Args>
     [[nodiscard]] meta_any construct(Args &&...args) const {
-        return construct(std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
+        return construct(std::array<meta_any, sizeof...(Args)>{meta_any{context(), std::forward<Args>(args)}...}.data(), sizeof...(Args));
         // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
     }
 
@@ -1427,7 +1427,7 @@ public:
      * @return A wrapper that references the given instance.
      */
     [[nodiscard]] meta_any from_void(void *elem, bool transfer_ownership = false) const {
-        return ((elem != nullptr) && (node.from_void != nullptr)) ? node.from_void(*ctx, elem, transfer_ownership ? elem : nullptr) : meta_any{meta_ctx_arg, *ctx};
+        return ((elem != nullptr) && (node.from_void != nullptr)) ? node.from_void(context(), elem, transfer_ownership ? elem : nullptr) : meta_any{meta_ctx_arg, context()};
     }
 
     /**
@@ -1436,7 +1436,7 @@ public:
      * @return A wrapper that references the given instance.
      */
     [[nodiscard]] meta_any from_void(const void *elem) const {
-        return ((elem != nullptr) && (node.from_void != nullptr)) ? node.from_void(*ctx, nullptr, elem) : meta_any{meta_ctx_arg, *ctx};
+        return ((elem != nullptr) && (node.from_void != nullptr)) ? node.from_void(context(), nullptr, elem) : meta_any{meta_ctx_arg, context()};
     }
 
     /**
@@ -1452,7 +1452,7 @@ public:
         if(node.details) {
             if(auto *elem = internal::find_member<&internal::meta_func_node::id>(node.details->func, id); elem != nullptr) {
                 if(const auto *candidate = lookup(args, sz, (instance->base().policy() == any_policy::cref), [curr = elem]() mutable { return (curr != nullptr) ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) {
-                    return candidate->invoke(*ctx, meta_handle{*ctx, std::move(instance)}, args);
+                    return candidate->invoke(context(), meta_handle{context(), std::move(instance)}, args);
                 }
             }
         }
@@ -1463,7 +1463,7 @@ public:
             }
         }
 
-        return meta_any{meta_ctx_arg, *ctx};
+        return meta_any{meta_ctx_arg, context()};
     }
 
     /**
@@ -1477,7 +1477,7 @@ public:
     template<typename... Args>
     // NOLINTNEXTLINE(modernize-use-nodiscard)
     meta_any invoke(const id_type id, meta_handle instance, Args &&...args) const {
-        return invoke(id, std::move(instance), std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
+        return invoke(id, std::move(instance), std::array<meta_any, sizeof...(Args)>{meta_any{context(), std::forward<Args>(args)}...}.data(), sizeof...(Args));
     }
 
     /**
@@ -1503,7 +1503,7 @@ public:
      */
     [[nodiscard]] meta_any get(const id_type id, meta_handle instance) const {
         const auto candidate = data(id);
-        return candidate ? candidate.get(std::move(instance)) : meta_any{meta_ctx_arg, *ctx};
+        return candidate ? candidate.get(std::move(instance)) : meta_any{meta_ctx_arg, context()};
     }
 
     /*! @copydoc meta_data::traits */
@@ -1528,12 +1528,11 @@ public:
     /*! @copydoc meta_data::operator== */
     [[nodiscard]] bool operator==(const meta_type &other) const noexcept {
         // NOLINTNEXTLINE(clang-analyzer-core.NonNullParamChecker)
-        return (ctx == other.ctx) && ((node.info == nullptr) == (other.node.info == nullptr)) && (node.info == nullptr || (*node.info == *other.node.info));
+        return (&context() == &other.context()) && ((node.info == nullptr) == (other.node.info == nullptr)) && (node.info == nullptr || (*node.info == *other.node.info));
     }
 
 private:
     internal::meta_type_node node{};
-    const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
 };
 
 /**

+ 13 - 0
test/entt/meta/meta_type.cpp

@@ -205,6 +205,19 @@ TEST_F(MetaType, Resolve) {
     ASSERT_TRUE(found);
 }
 
+TEST_F(MetaType, Context) {
+    entt::meta_type type{};
+    entt::meta_ctx ctx{};
+
+    ASSERT_EQ(&type.context(), &entt::locator<entt::meta_ctx>::value_or());
+    ASSERT_NE(&type.context(), &ctx);
+
+    type = entt::meta_type{ctx, entt::internal::meta_type_node{}};
+
+    ASSERT_NE(&type.context(), &entt::locator<entt::meta_ctx>::value_or());
+    ASSERT_EQ(&type.context(), &ctx);
+}
+
 TEST_F(MetaType, SafeWhenEmpty) {
     using namespace entt::literals;