From f30ca72c69b3fae1830240adc599d6c080ea1c27 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Wed, 5 Feb 2025 10:34:50 +0100 Subject: [PATCH] meta: make meta_type return the underlying context --- TODO | 1 + src/entt/meta/meta.hpp | 55 ++++++++++++++++++------------------ test/entt/meta/meta_type.cpp | 13 +++++++++ 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/TODO b/TODO index 790a5e800..e20b1d6bd 100644 --- a/TODO +++ b/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) diff --git a/src/entt/meta/meta.hpp b/src/entt/meta/meta.hpp index aa323510d..3e1de05b3 100644 --- a/src/entt/meta/meta.hpp +++ b/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 [[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(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(args), 1) + ... + 0u); }) != 0u); } /** @@ -1347,7 +1347,7 @@ public: */ [[nodiscard]] meta_range base() const noexcept { using range_type = meta_range; - 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 data() const noexcept { using range_type = meta_range; - 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 func() const noexcept { using return_type = meta_range; - 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 [[nodiscard]] meta_any construct(Args &&...args) const { - return construct(std::array{meta_any{*ctx, std::forward(args)}...}.data(), sizeof...(Args)); + return construct(std::array{meta_any{context(), std::forward(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 // 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{*ctx, std::forward(args)}...}.data(), sizeof...(Args)); + return invoke(id, std::move(instance), std::array{meta_any{context(), std::forward(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::value_or()}; }; /** diff --git a/test/entt/meta/meta_type.cpp b/test/entt/meta/meta_type.cpp index 129611455..5267269b1 100644 --- a/test/entt/meta/meta_type.cpp +++ b/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::value_or()); + ASSERT_NE(&type.context(), &ctx); + + type = entt::meta_type{ctx, entt::internal::meta_type_node{}}; + + ASSERT_NE(&type.context(), &entt::locator::value_or()); + ASSERT_EQ(&type.context(), &ctx); +} + TEST_F(MetaType, SafeWhenEmpty) { using namespace entt::literals;