diff --git a/src/entt/meta/factory.hpp b/src/entt/meta/factory.hpp index a0d66f606..c7d3bf0b1 100644 --- a/src/entt/meta/factory.hpp +++ b/src/entt/meta/factory.hpp @@ -29,7 +29,7 @@ namespace entt { namespace internal { -inline decltype(auto) owner(const type_info &info, meta_ctx &ctx) { +inline decltype(auto) owner(meta_ctx &ctx, const type_info &info) { auto &&context = internal::meta_context::from(ctx); ENTT_ASSERT(context.value.contains(info.hash()), "Type not available"); return context.value[info.hash()]; @@ -96,7 +96,7 @@ class meta_factory { static_assert(Policy::template value, "Invalid return type for the given policy"); auto &&elem = internal::meta_extend( - internal::owner(*info, *ctx), + internal::owner(*ctx, *info), id, internal::meta_data_node{ /* this is never static */ @@ -104,7 +104,7 @@ class meta_factory { Setter::size, &internal::resolve>>, &meta_arg::size != 1u, type_list_element_t>...>>, - +[](meta_handle instance, meta_any value, const meta_ctx &area) { return (meta_setter>(*instance.operator->(), value.as_ref(), area) || ...); }, + +[](const meta_ctx &area, meta_handle instance, meta_any value) { return (meta_setter>(area, *instance.operator->(), value.as_ref()) || ...); }, &meta_getter}); bucket = &elem.prop; @@ -123,7 +123,7 @@ public: : ctx{&area}, bucket{}, info{&type_id()} { - auto &&elem = internal::owner(*info, *ctx); + auto &&elem = internal::owner(*ctx, *info); if(!elem.details) { elem.details = std::make_shared(); @@ -138,8 +138,8 @@ public: * @return An extended meta factory for the given type. */ auto type(const id_type id) noexcept { - auto &&elem = internal::owner(*info, *ctx); - ENTT_ASSERT(elem.id == id || !resolve(id, *ctx), "Duplicate identifier"); + auto &&elem = internal::owner(*ctx, *info); + ENTT_ASSERT(elem.id == id || !resolve(*ctx, id), "Duplicate identifier"); bucket = &elem.details->prop; elem.id = id; return *this; @@ -158,7 +158,7 @@ public: static_assert(!std::is_same_v && std::is_base_of_v, "Invalid base type"); internal::meta_extend( - internal::owner(*info, *ctx), + internal::owner(*ctx, *info), type_id().hash(), internal::meta_base_node{ &internal::resolve, @@ -187,11 +187,11 @@ public: using conv_type = std::remove_cv_t>>; internal::meta_extend( - internal::owner(*info, *ctx), + internal::owner(*ctx, *info), type_id().hash(), internal::meta_conv_node{ - +[](const void *instance, const meta_ctx &area) { - return forward_as_meta(std::invoke(Candidate, *static_cast(instance)), area); + +[](const meta_ctx &area, const void *instance) { + return forward_as_meta(area, std::invoke(Candidate, *static_cast(instance))); }}); bucket = nullptr; @@ -212,11 +212,11 @@ public: using conv_type = std::remove_cv_t>; internal::meta_extend( - internal::owner(*info, *ctx), + internal::owner(*ctx, *info), type_id().hash(), internal::meta_conv_node{ - +[](const void *instance, const meta_ctx &area) { - return forward_as_meta(static_cast(*static_cast(instance)), area); + +[](const meta_ctx &area, const void *instance) { + return forward_as_meta(area, static_cast(*static_cast(instance))); }}); bucket = nullptr; @@ -239,11 +239,12 @@ public: template auto ctor() noexcept { using descriptor = meta_function_helper_t; + static_assert(std::is_base_of_v, "Unknown policy type"); static_assert(Policy::template value, "Invalid return type for the given policy"); static_assert(std::is_same_v>, Type>, "The function doesn't return an object of the required type"); internal::meta_extend( - internal::owner(*info, *ctx), + internal::owner(*ctx, *info), type_id().hash(), internal::meta_ctor_node{ descriptor::args_type::size, @@ -269,7 +270,7 @@ public: using descriptor = meta_function_helper_t; internal::meta_extend( - internal::owner(*info, *ctx), + internal::owner(*ctx, *info), type_id().hash(), internal::meta_ctor_node{ descriptor::args_type::size, @@ -303,7 +304,7 @@ public: static_assert(std::is_invocable_v, "The function doesn't accept an object of the type provided"); internal::meta_extend( - internal::owner(*info, *ctx), + internal::owner(*ctx, *info), internal::meta_dtor_node{ +[](void *instance) { std::invoke(Func, *static_cast(instance)); }}); @@ -326,11 +327,13 @@ public: */ template auto data(const id_type id) noexcept { + static_assert(std::is_base_of_v, "Unknown policy type"); + if constexpr(std::is_member_object_pointer_v) { using data_type = std::remove_reference_t>; auto &&elem = internal::meta_extend( - internal::owner(*info, *ctx), + internal::owner(*ctx, *info), id, internal::meta_data_node{ /* this is never static */ @@ -346,7 +349,7 @@ public: using data_type = std::remove_reference_t>; auto &&elem = internal::meta_extend( - internal::owner(*info, *ctx), + internal::owner(*ctx, *info), id, internal::meta_data_node{ ((std::is_same_v> || std::is_const_v) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static, @@ -385,11 +388,12 @@ public: template auto data(const id_type id) noexcept { using data_type = std::invoke_result_t; + static_assert(std::is_base_of_v, "Unknown policy type"); static_assert(Policy::template value, "Invalid return type for the given policy"); if constexpr(std::is_same_v) { auto &&elem = internal::meta_extend( - internal::owner(*info, *ctx), + internal::owner(*ctx, *info), id, internal::meta_data_node{ /* this is never static */ @@ -405,7 +409,7 @@ public: using args_type = typename meta_function_helper_t::args_type; auto &&elem = internal::meta_extend( - internal::owner(*info, *ctx), + internal::owner(*ctx, *info), id, internal::meta_data_node{ /* this is never static nor const */ @@ -441,6 +445,7 @@ public: */ template auto data(const id_type id) noexcept { + static_assert(std::is_base_of_v, "Unknown policy type"); data(id, std::make_index_sequence{}); return *this; } @@ -461,10 +466,11 @@ public: template auto func(const id_type id) noexcept { using descriptor = meta_function_helper_t; + static_assert(std::is_base_of_v, "Unknown policy type"); static_assert(Policy::template value, "Invalid return type for the given policy"); auto &&elem = internal::meta_extend( - internal::owner(*info, *ctx), + internal::owner(*ctx, *info), id, internal::meta_func_node{ (descriptor::is_const ? internal::meta_traits::is_const : internal::meta_traits::is_none) | (descriptor::is_static ? internal::meta_traits::is_static : internal::meta_traits::is_none), @@ -528,13 +534,29 @@ private: * @return A meta factory for the given type. */ template -[[nodiscard]] auto meta(meta_ctx &ctx = locator::value_or()) noexcept { +[[nodiscard]] auto meta(meta_ctx &ctx) noexcept { auto &&context = internal::meta_context::from(ctx); // make sure the type exists in the context before returning a factory context.value.try_emplace(type_id().hash(), internal::resolve(context)); return meta_factory{ctx}; } +/** + * @brief Utility function to use for reflection. + * + * This is the point from which everything starts.
+ * By invoking this function with a type that is not yet reflected, a meta type + * is created to which it will be possible to attach meta objects through a + * dedicated factory. + * + * @tparam Type Type to reflect. + * @return A meta factory for the given type. + */ +template +[[nodiscard]] auto meta() noexcept { + return meta(locator::value_or()); +} + /** * @brief Resets a type and all its parts. * @@ -547,7 +569,7 @@ template * @param id Unique identifier. * @param ctx The context from which to reset meta types. */ -inline void meta_reset(const id_type id, meta_ctx &ctx = locator::value_or()) noexcept { +inline void meta_reset(meta_ctx &ctx, const id_type id) noexcept { auto &&context = internal::meta_context::from(ctx); for(auto it = context.value.begin(); it != context.value.end();) { @@ -559,6 +581,21 @@ inline void meta_reset(const id_type id, meta_ctx &ctx = locator::valu } } +/** + * @brief Resets a type and all its parts. + * + * Resets a type and all its data members, member functions and properties, as + * well as its constructors, destructors and conversion functions if any.
+ * Base classes aren't reset but the link between the two types is removed. + * + * The type is also removed from the set of searchable types. + * + * @param id Unique identifier. + */ +inline void meta_reset(const id_type id) noexcept { + meta_reset(locator::value_or(), id); +} + /** * @brief Resets a type and all its parts. * @@ -568,10 +605,22 @@ inline void meta_reset(const id_type id, meta_ctx &ctx = locator::valu * @param ctx The context from which to reset meta types. */ template -void meta_reset(meta_ctx &ctx = locator::value_or()) noexcept { +void meta_reset(meta_ctx &ctx) noexcept { internal::meta_context::from(ctx).value.erase(type_id().hash()); } +/** + * @brief Resets a type and all its parts. + * + * @sa meta_reset + * + * @tparam Type Type to reset. + */ +template +void meta_reset() noexcept { + meta_reset(locator::value_or()); +} + /** * @brief Resets all meta types. * @@ -579,10 +628,19 @@ void meta_reset(meta_ctx &ctx = locator::value_or()) noexcept { * * @param ctx The context from which to reset meta types. */ -inline void meta_reset(meta_ctx &ctx = locator::value_or()) noexcept { +inline void meta_reset(meta_ctx &ctx) noexcept { internal::meta_context::from(ctx).value.clear(); } +/** + * @brief Resets all meta types. + * + * @sa meta_reset + */ +inline void meta_reset() noexcept { + meta_reset(locator::value_or()); +} + } // namespace entt #endif diff --git a/src/entt/meta/meta.hpp b/src/entt/meta/meta.hpp index 9109c91fa..a6acbd3d2 100644 --- a/src/entt/meta/meta.hpp +++ b/src/entt/meta/meta.hpp @@ -187,18 +187,22 @@ class meta_any { } } - meta_any(const meta_any &other, any ref, const meta_ctx &area) noexcept + meta_any(const meta_ctx &area, const meta_any &other, any ref) noexcept : storage{std::move(ref)}, ctx{&area}, node{storage ? other.node : internal::meta_type_node{}}, vtable{storage ? other.vtable : &basic_vtable} {} public: + /*! Default constructor. */ + meta_any() noexcept + : meta_any{locator::value_or()} {} + /** * @brief Context aware constructor. * @param area The context from which to search for meta types. */ - meta_any(const meta_ctx &area = locator::value_or()) noexcept + meta_any(const meta_ctx &area) noexcept : storage{}, ctx{&area}, node{}, @@ -222,7 +226,7 @@ public: * @tparam Type Type of object to use to initialize the wrapper. * @param value An instance of an object to use to initialize the wrapper. */ - template, meta_any>>> + template, meta_any> && !std::is_same_v, meta_ctx>>> meta_any(Type &&value) : meta_any{std::in_place_type>, std::forward(value)} {} @@ -350,7 +354,7 @@ public: template [[nodiscard]] const Type *try_cast() const { const auto other = internal::resolve>(internal::meta_context::from(*ctx)); - return static_cast(internal::try_cast(node, other, data(), internal::meta_context::from(*ctx))); + return static_cast(internal::try_cast(internal::meta_context::from(*ctx), node, other, data())); } /*! @copydoc try_cast */ @@ -360,7 +364,7 @@ public: return std::as_const(*this).try_cast>(); } else { const auto other = internal::resolve>(internal::meta_context::from(*ctx)); - return static_cast(const_cast(internal::try_cast(node, other, data(), internal::meta_context::from(*ctx)))); + return static_cast(const_cast(internal::try_cast(internal::meta_context::from(*ctx), node, other, data()))); } } @@ -428,7 +432,7 @@ public: return {}; } else { auto target = internal::resolve>>(internal::meta_context::from(*ctx)); - return allow_cast({target, *ctx}); + return allow_cast({*ctx, target}); } } @@ -442,9 +446,9 @@ public: auto target = internal::resolve>>(internal::meta_context::from(*ctx)); if constexpr(std::is_reference_v && !std::is_const_v>) { - return allow_cast({target, *ctx}) && (storage.data() != nullptr); + return allow_cast({*ctx, target}) && (storage.data() != nullptr); } else { - return allow_cast({target, *ctx}); + return allow_cast({*ctx, target}); } } @@ -540,12 +544,12 @@ public: /*! @copydoc any::as_ref */ [[nodiscard]] meta_any as_ref() noexcept { - return meta_any{*this, storage.as_ref(), *ctx}; + return meta_any{*ctx, *this, storage.as_ref()}; } /*! @copydoc any::as_ref */ [[nodiscard]] meta_any as_ref() const noexcept { - return meta_any{*this, storage.as_ref(), *ctx}; + return meta_any{*ctx, *this, storage.as_ref()}; } /*! @copydoc any::owner */ @@ -580,13 +584,24 @@ meta_any make_meta(Args &&...args) { * @return A properly initialized and not necessarily owning wrapper. */ template -meta_any forward_as_meta(Type &&value, const meta_ctx &ctx = locator::value_or()) { +meta_any forward_as_meta(const meta_ctx &ctx, Type &&value) { // TODO it would be great if we had value and context construction support for meta_any meta_any elem{ctx}; elem.emplace(std::forward(value)); return elem; } +/** + * @brief Forwards its argument and avoids copies for lvalue references. + * @tparam Type Type of argument to use to construct the new instance. + * @param value Parameter to use to construct the instance. + * @return A properly initialized and not necessarily owning wrapper. + */ +template +meta_any forward_as_meta(Type &&value) { + return forward_as_meta(locator::value_or(), std::forward(value)); +} + /** * @brief Opaque pointers to instances of any type. * @@ -666,10 +681,10 @@ struct meta_prop { /** * @brief Context aware constructor for meta objects. - * @param curr The underlying node with which to construct the instance. * @param area The context from which to search for meta types. + * @param curr The underlying node with which to construct the instance. */ - meta_prop(const internal::meta_prop_node &curr, const meta_ctx &area) noexcept + meta_prop(const meta_ctx &area, const internal::meta_prop_node &curr) noexcept : node{&curr}, ctx{&area} {} @@ -678,7 +693,7 @@ struct meta_prop { * @return A wrapper containing the value stored with the property. */ [[nodiscard]] meta_any value() const { - return node->value ? node->type(internal::meta_context::from(*ctx)).from_void(nullptr, node->value.get(), *ctx) : meta_any{}; + return node->value ? node->type(internal::meta_context::from(*ctx)).from_void(*ctx, nullptr, node->value.get()) : meta_any{}; } /** @@ -706,10 +721,10 @@ struct meta_data { /** * @brief Context aware constructor for meta objects. - * @param curr The underlying node with which to construct the instance. * @param area The context from which to search for meta types. + * @param curr The underlying node with which to construct the instance. */ - meta_data(const internal::meta_data_node &curr, const meta_ctx &area) noexcept + meta_data(const meta_ctx &area, const internal::meta_data_node &curr) noexcept : node{&curr}, ctx{&area} {} @@ -755,7 +770,7 @@ struct meta_data { */ template bool set(meta_handle instance, Type &&value) const { - return node->set && node->set(std::move(instance), std::forward(value), *ctx); + return node->set && node->set(*ctx, std::move(instance), std::forward(value)); } /** @@ -768,7 +783,7 @@ struct meta_data { * @return A wrapper containing the value of the underlying variable. */ [[nodiscard]] meta_any get(meta_handle instance) const { - return node->get(std::move(instance), *ctx); + return node->get(*ctx, std::move(instance)); } /** @@ -783,7 +798,7 @@ struct meta_data { * @return An iterable range to visit registered meta properties. */ [[nodiscard]] meta_range prop() const noexcept { - return {{node->prop.cbegin(), *ctx}, {node->prop.cend(), *ctx}}; + return {{*ctx, node->prop.cbegin()}, {*ctx, node->prop.cend()}}; } /** @@ -793,7 +808,7 @@ struct meta_data { */ [[nodiscard]] meta_prop prop(const id_type key) const { const auto it = node->prop.find(key); - return it != node->prop.cend() ? meta_prop{it->second, *ctx} : meta_prop{}; + return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{}; } /** @@ -821,10 +836,10 @@ struct meta_func { /** * @brief Context aware constructor for meta objects. - * @param curr The underlying node with which to construct the instance. * @param area The context from which to search for meta types. + * @param curr The underlying node with which to construct the instance. */ - meta_func(const internal::meta_func_node &curr, const meta_ctx &area) noexcept + meta_func(const meta_ctx &area, const internal::meta_func_node &curr) noexcept : node{&curr}, ctx{&area} {} @@ -880,7 +895,7 @@ struct meta_func { * @return A wrapper containing the returned value, if any. */ meta_any invoke(meta_handle instance, meta_any *const args, const size_type sz) const { - return sz == arity() ? node->invoke(std::move(instance), args, *ctx) : meta_any{}; + return sz == arity() ? node->invoke(*ctx, std::move(instance), args) : meta_any{}; } /** @@ -901,7 +916,7 @@ struct meta_func { /*! @copydoc meta_data::prop */ [[nodiscard]] meta_range prop() const noexcept { - return {{node->prop.cbegin(), *ctx}, {node->prop.cend(), *ctx}}; + return {{*ctx, node->prop.cbegin()}, {*ctx, node->prop.cend()}}; } /** @@ -911,7 +926,7 @@ struct meta_func { */ [[nodiscard]] meta_prop prop(const id_type key) const { const auto it = node->prop.find(key); - return it != node->prop.cend() ? meta_prop{it->second, *ctx} : meta_prop{}; + return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{}; } /** @@ -919,7 +934,7 @@ struct meta_func { * @return The next overload of the given function, if any. */ [[nodiscard]] meta_func next() const { - return node->next ? meta_func{*node->next, *ctx} : meta_func{}; + return node->next ? meta_func{*ctx, *node->next} : meta_func{}; } /** @@ -955,7 +970,7 @@ class meta_type { size_type pos{}; for(; pos < sz && args[pos]; ++pos) { - const auto other = curr->arg(pos, *ctx); + const auto other = curr->arg(*ctx, pos); const auto type = args[pos].type(); if(const auto &info = other.info(); info == type.info()) { @@ -1011,20 +1026,20 @@ public: /** * @brief Context aware constructor for meta objects. - * @param curr The underlying node with which to construct the instance. * @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 internal::meta_type_node &curr, const meta_ctx &area) noexcept + meta_type(const meta_ctx &area, const internal::meta_type_node &curr) noexcept : node{curr}, ctx{&area} {} /** * @brief Context aware constructor for meta objects. - * @param curr The underlying node with which to construct the instance. * @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 internal::meta_base_node &curr, const meta_ctx &area) noexcept - : meta_type{curr.type(internal::meta_context::from(area)), area} {} + 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. @@ -1113,7 +1128,7 @@ public: * doesn't refer to a pointer type. */ [[nodiscard]] meta_type remove_pointer() const noexcept { - return {node.remove_pointer(internal::meta_context::from(*ctx)), *ctx}; + return {*ctx, node.remove_pointer(internal::meta_context::from(*ctx))}; } /** @@ -1167,7 +1182,7 @@ public: * @return The tag for the class template of the underlying type. */ [[nodiscard]] inline meta_type template_type() const noexcept { - return node.templ.type ? meta_type{node.templ.type(internal::meta_context::from(*ctx)), *ctx} : meta_type{}; + return node.templ.type ? meta_type{*ctx, node.templ.type(internal::meta_context::from(*ctx))} : meta_type{}; } /** @@ -1176,7 +1191,7 @@ public: * @return The type of the i-th template argument of a type. */ [[nodiscard]] inline meta_type template_arg(const size_type index) const noexcept { - return index < template_arity() ? meta_type{node.templ.arg(index, internal::meta_context::from(*ctx)), *ctx} : meta_type{}; + return index < template_arity() ? meta_type{*ctx, node.templ.arg(internal::meta_context::from(*ctx), index)} : meta_type{}; } /** @@ -1185,7 +1200,7 @@ public: */ [[nodiscard]] meta_range base() const noexcept { using range_type = meta_range; - return node.details ? range_type{{node.details->base.cbegin(), *ctx}, {node.details->base.cend(), *ctx}} : range_type{}; + return node.details ? range_type{{*ctx, node.details->base.cbegin()}, {*ctx, node.details->base.cend()}} : range_type{}; } /** @@ -1194,7 +1209,7 @@ public: */ [[nodiscard]] meta_range data() const noexcept { using range_type = meta_range; - return node.details ? range_type{{node.details->data.cbegin(), *ctx}, {node.details->data.cend(), *ctx}} : range_type{}; + return node.details ? range_type{{*ctx, node.details->data.cbegin()}, {*ctx, node.details->data.cend()}} : range_type{}; } /** @@ -1208,7 +1223,7 @@ public: [[nodiscard]] meta_data data(const id_type id) const { if(node.details) { if(const auto it = node.details->data.find(id); it != node.details->data.cend()) { - return meta_data{it->second, *ctx}; + return meta_data{*ctx, it->second}; } } @@ -1221,7 +1236,7 @@ public: */ [[nodiscard]] meta_range func() const noexcept { using return_type = meta_range; - return node.details ? return_type{{node.details->func.cbegin(), *ctx}, {node.details->func.cend(), *ctx}} : return_type{}; + return node.details ? return_type{{*ctx, node.details->func.cbegin()}, {*ctx, node.details->func.cend()}} : return_type{}; } /** @@ -1237,7 +1252,7 @@ public: [[nodiscard]] meta_func func(const id_type id) const { if(node.details) { if(const auto it = node.details->func.find(id); it != node.details->func.cend()) { - return meta_func{it->second, *ctx}; + return meta_func{*ctx, it->second}; } } @@ -1262,7 +1277,7 @@ public: }); if(candidate) { - return candidate->invoke(args, *ctx); + return candidate->invoke(*ctx, args); } } @@ -1294,12 +1309,12 @@ public: * @return A wrapper that references the given instance. */ meta_any from_void(void *element) const { - return (element && node.from_void) ? node.from_void(element, nullptr, *ctx) : meta_any{}; + return (element && node.from_void) ? node.from_void(*ctx, element, nullptr) : meta_any{}; } /*! @copydoc from_void */ meta_any from_void(const void *element) const { - return (element && node.from_void) ? node.from_void(nullptr, element, *ctx) : meta_any{}; + return (element && node.from_void) ? node.from_void(*ctx, nullptr, element) : meta_any{}; } /** @@ -1324,7 +1339,7 @@ public: }); if(candidate) { - return candidate->invoke(std::move(instance), args, *ctx); + return candidate->invoke(*ctx, std::move(instance), args); } } } @@ -1390,7 +1405,7 @@ public: */ [[nodiscard]] meta_range prop() const noexcept { using range_type = meta_range; - return node.details ? range_type{{node.details->prop.cbegin(), *ctx}, {node.details->prop.cend(), *ctx}} : range_type{}; + return node.details ? range_type{{*ctx, node.details->prop.cbegin()}, {*ctx, node.details->prop.cend()}} : range_type{}; } /** @@ -1404,7 +1419,7 @@ public: [[nodiscard]] meta_prop prop(const id_type key) const { if(node.details) { if(const auto it = node.details->prop.find(key); it != node.details->prop.cend()) { - return meta_prop{it->second, *ctx}; + return meta_prop{*ctx, it->second}; } } @@ -1444,7 +1459,7 @@ private: } [[nodiscard]] inline meta_type meta_any::type() const noexcept { - return node.info ? meta_type{node, *ctx} : meta_type{}; + return node.info ? meta_type{*ctx, node} : meta_type{}; } template @@ -1477,7 +1492,7 @@ bool meta_any::set(const id_type id, Type &&value) { if(const auto *value = data(); node.details) { for(auto &&curr: node.details->base) { - const auto &as_const = curr.second.type(internal::meta_context::from(*ctx)).from_void(nullptr, curr.second.cast(value), *ctx); + const auto &as_const = curr.second.type(internal::meta_context::from(*ctx)).from_void(*ctx, nullptr, curr.second.cast(value)); if(auto other = as_const.allow_cast(type); other) { return other; @@ -1485,7 +1500,7 @@ bool meta_any::set(const id_type id, Type &&value) { } if(auto it = node.details->conv.find(type.info().hash()); it != node.details->conv.cend()) { - return it->second.conv(data(), *ctx); + return it->second.conv(*ctx, data()); } } @@ -1502,7 +1517,7 @@ bool meta_any::set(const id_type id, Type &&value) { } inline bool meta_any::assign(const meta_any &other) { - auto value = other.allow_cast({node, *ctx}); + auto value = other.allow_cast({*ctx, node}); return value && storage.assign(std::move(value.storage)); } @@ -1515,19 +1530,19 @@ inline bool meta_any::assign(meta_any &&other) { } [[nodiscard]] inline meta_type meta_data::type() const noexcept { - return {node->type(internal::meta_context::from(*ctx)), *ctx}; + return {*ctx, node->type(internal::meta_context::from(*ctx))}; } [[nodiscard]] inline meta_type meta_data::arg(const size_type index) const noexcept { - return index < arity() ? node->arg(index, *ctx) : meta_type{}; + return index < arity() ? node->arg(*ctx, index) : meta_type{}; } [[nodiscard]] inline meta_type meta_func::ret() const noexcept { - return {node->ret(internal::meta_context::from(*ctx)), *ctx}; + return {*ctx, node->ret(internal::meta_context::from(*ctx))}; } [[nodiscard]] inline meta_type meta_func::arg(const size_type index) const noexcept { - return index < arity() ? node->arg(index, *ctx) : meta_type{}; + return index < arity() ? node->arg(*ctx, index) : meta_type{}; } /** @@ -1714,7 +1729,7 @@ private: */ [[nodiscard]] inline meta_type meta_sequence_container::value_type() const noexcept { auto &&ctx_TODO = locator::value_or(); - return value_type_node ? meta_type{value_type_node(), ctx_TODO} : meta_type{}; + return value_type_node ? meta_type{ctx_TODO, value_type_node()} : meta_type{}; } /** @@ -1811,7 +1826,7 @@ inline meta_sequence_container::iterator meta_sequence_container::erase(iterator */ [[nodiscard]] inline meta_type meta_associative_container::key_type() const noexcept { auto &&ctx_TODO = locator::value_or(); - return key_type_node ? meta_type{key_type_node(), ctx_TODO} : meta_type{}; + return key_type_node ? meta_type{ctx_TODO, key_type_node()} : meta_type{}; } /** @@ -1820,13 +1835,13 @@ inline meta_sequence_container::iterator meta_sequence_container::erase(iterator */ [[nodiscard]] inline meta_type meta_associative_container::mapped_type() const noexcept { auto &&ctx_TODO = locator::value_or(); - return mapped_type_node ? meta_type{mapped_type_node(), ctx_TODO} : meta_type{}; + return mapped_type_node ? meta_type{ctx_TODO, mapped_type_node()} : meta_type{}; } /*! @copydoc meta_sequence_container::value_type */ [[nodiscard]] inline meta_type meta_associative_container::value_type() const noexcept { auto &&ctx_TODO = locator::value_or(); - return value_type_node ? meta_type{value_type_node(), ctx_TODO} : meta_type{}; + return value_type_node ? meta_type{ctx_TODO, value_type_node()} : meta_type{}; } /*! @copydoc meta_sequence_container::size */ diff --git a/src/entt/meta/node.hpp b/src/entt/meta/node.hpp index 0eb2552a3..51aac7bab 100644 --- a/src/entt/meta/node.hpp +++ b/src/entt/meta/node.hpp @@ -59,15 +59,15 @@ struct meta_base_node { }; struct meta_conv_node { - meta_any (*conv)(const void *, const meta_ctx &){}; + meta_any (*conv)(const meta_ctx &, const void *){}; }; struct meta_ctor_node { using size_type = std::size_t; size_type arity{0u}; - meta_type (*arg)(const size_type, const meta_ctx &) noexcept {}; - meta_any (*invoke)(meta_any *const, const meta_ctx &){}; + meta_type (*arg)(const meta_ctx &, const size_type) noexcept {}; + meta_any (*invoke)(const meta_ctx &, meta_any *const){}; }; struct meta_dtor_node { @@ -80,9 +80,9 @@ struct meta_data_node { meta_traits traits{meta_traits::is_none}; size_type arity{0u}; meta_type_node (*type)(const meta_context &) noexcept {}; - meta_type (*arg)(const size_type, const meta_ctx &) noexcept {}; - bool (*set)(meta_handle, meta_any, const meta_ctx &){}; - meta_any (*get)(meta_handle, const meta_ctx &){}; + meta_type (*arg)(const meta_ctx &, const size_type) noexcept {}; + bool (*set)(const meta_ctx &, meta_handle, meta_any){}; + meta_any (*get)(const meta_ctx &, meta_handle){}; dense_map prop{}; }; @@ -92,8 +92,8 @@ struct meta_func_node { meta_traits traits{meta_traits::is_none}; size_type arity{0u}; meta_type_node (*ret)(const meta_context &) noexcept {}; - meta_type (*arg)(const size_type, const meta_ctx &) noexcept {}; - meta_any (*invoke)(meta_handle, meta_any *const, const meta_ctx &){}; + meta_type (*arg)(const meta_ctx &, const size_type) noexcept {}; + meta_any (*invoke)(const meta_ctx &, meta_handle, meta_any *const){}; std::shared_ptr next{}; dense_map prop{}; }; @@ -103,7 +103,7 @@ struct meta_template_node { size_type arity{0u}; meta_type_node (*type)(const meta_context &) noexcept {}; - meta_type_node (*arg)(const size_type, const meta_context &) noexcept {}; + meta_type_node (*arg)(const meta_context &, const size_type) noexcept {}; }; struct meta_type_descriptor { @@ -125,7 +125,7 @@ struct meta_type_node { meta_type_node (*remove_pointer)(const meta_context &) noexcept {}; meta_any (*default_constructor)(const meta_ctx &){}; double (*conversion_helper)(void *, const void *){}; - meta_any (*from_void)(void *, const void *, const meta_ctx &){}; + meta_any (*from_void)(const meta_ctx &, void *, const void *){}; meta_template_node templ{}; meta_dtor_node dtor{}; std::shared_ptr details{}; @@ -140,7 +140,7 @@ template } template -[[nodiscard]] auto meta_arg_node(type_list, [[maybe_unused]] const std::size_t index, const meta_context &context) noexcept { +[[nodiscard]] auto meta_arg_node(const meta_context &context, type_list, [[maybe_unused]] const std::size_t index) noexcept { std::size_t pos{}; meta_type_node (*value)(const meta_context &) noexcept = nullptr; ((value = (pos++ == index ? &resolve>> : value)), ...); @@ -148,14 +148,14 @@ template return value(context); } -[[nodiscard]] inline const void *try_cast(const meta_type_node &from, const meta_type_node &to, const void *instance, const meta_context &context) noexcept { +[[nodiscard]] inline const void *try_cast(const meta_context &context, const meta_type_node &from, const meta_type_node &to, const void *instance) noexcept { if(from.info && to.info && *from.info == *to.info) { return instance; } if(from.details) { for(auto &&curr: from.details->base) { - if(const void *elem = try_cast(curr.second.type(context), to, curr.second.cast(instance), context); elem) { + if(const void *elem = try_cast(context, curr.second.type(context), to, curr.second.cast(instance)); elem) { return elem; } } @@ -164,7 +164,7 @@ template return nullptr; } -[[nodiscard]] inline const meta_type_node *try_resolve(const type_info &info, const meta_context &context) noexcept { +[[nodiscard]] inline const meta_type_node *try_resolve(const meta_context &context, const type_info &info) noexcept { const auto it = context.value.find(info.hash()); return it != context.value.end() ? &it->second : nullptr; } @@ -197,7 +197,7 @@ void meta_conversion_helper([[maybe_unused]] meta_type_node &node) { template void meta_from_void([[maybe_unused]] meta_type_node &node) { if constexpr(!std::is_same_v && !std::is_function_v) { - node.from_void = +[](void *element, const void *as_const, const meta_ctx &ctx) { + node.from_void = +[](const meta_ctx &ctx, void *element, const void *as_const) { // TODO it would be great if we had value and context construction support for meta_any meta_any elem{ctx}; element ? elem.emplace &>(*static_cast *>(element)) : elem.emplace &>(*static_cast *>(as_const)); @@ -210,7 +210,7 @@ template [[nodiscard]] meta_type_node resolve(const meta_context &context) noexcept { static_assert(std::is_same_v>>, "Invalid type"); - if(auto *elem = try_resolve(type_id(), context); elem) { + if(auto *elem = try_resolve(context, type_id()); elem) { return *elem; } @@ -237,7 +237,7 @@ template node.templ = meta_template_node{ meta_template_traits::args_type::size, &resolve::class_type>, - +[](const std::size_t index, const meta_context &area) noexcept { return meta_arg_node(typename meta_template_traits::args_type{}, index, area); }}; + +[](const meta_context &area, const std::size_t index) noexcept { return meta_arg_node(area, typename meta_template_traits::args_type{}, index); }}; } return node; diff --git a/src/entt/meta/policy.hpp b/src/entt/meta/policy.hpp index 91bab4367..9fea4f68c 100644 --- a/src/entt/meta/policy.hpp +++ b/src/entt/meta/policy.hpp @@ -5,8 +5,11 @@ namespace entt { +/*! @brief Basic common class for meta policies. */ +struct meta_policy {}; + /*! @brief Empty class type used to request the _as ref_ policy. */ -struct as_ref_t { +struct as_ref_t final: meta_policy { /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. @@ -20,7 +23,7 @@ struct as_ref_t { }; /*! @brief Empty class type used to request the _as cref_ policy. */ -struct as_cref_t { +struct as_cref_t final: meta_policy { /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. @@ -34,7 +37,7 @@ struct as_cref_t { }; /*! @brief Empty class type used to request the _as-is_ policy. */ -struct as_is_t { +struct as_is_t final: meta_policy { /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. @@ -48,7 +51,7 @@ struct as_is_t { }; /*! @brief Empty class type used to request the _as void_ policy. */ -struct as_void_t { +struct as_void_t final: meta_policy { /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. diff --git a/src/entt/meta/range.hpp b/src/entt/meta/range.hpp index 487d82163..e3d8154c5 100644 --- a/src/entt/meta/range.hpp +++ b/src/entt/meta/range.hpp @@ -29,7 +29,7 @@ struct meta_range_iterator final { : it{}, ctx{} {} - meta_range_iterator(const It iter, const meta_ctx &area) noexcept + meta_range_iterator(const meta_ctx &area, const It iter) noexcept : it{iter}, ctx{&area} {} @@ -70,7 +70,7 @@ struct meta_range_iterator final { } [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { - return {it[value].first, Type{it[value].second, *ctx}}; + return {it[value].first, Type{*ctx, it[value].second}}; } [[nodiscard]] constexpr pointer operator->() const noexcept { @@ -78,7 +78,7 @@ struct meta_range_iterator final { } [[nodiscard]] constexpr reference operator*() const noexcept { - return {it->first, Type{it->second, *ctx}}; + return {it->first, Type{*ctx, it->second}}; } template diff --git a/src/entt/meta/resolve.hpp b/src/entt/meta/resolve.hpp index 79f958afb..eb2556b52 100644 --- a/src/entt/meta/resolve.hpp +++ b/src/entt/meta/resolve.hpp @@ -18,9 +18,19 @@ namespace entt { * @return The meta type associated with the given type, if any. */ template -[[nodiscard]] meta_type resolve(const meta_ctx &ctx = locator::value_or()) noexcept { +[[nodiscard]] meta_type resolve(const meta_ctx &ctx) noexcept { auto &&context = internal::meta_context::from(ctx); - return {internal::resolve>>(context), ctx}; + return {ctx, internal::resolve>>(context)}; +} + +/** + * @brief Returns the meta type associated with a given type. + * @tparam Type Type to use to search for a meta type. + * @return The meta type associated with the given type, if any. + */ +template +[[nodiscard]] meta_type resolve() noexcept { + return resolve(locator::value_or()); } /** @@ -28,18 +38,26 @@ template * @param ctx The context from which to search for meta types. * @return An iterable range to use to visit all meta types. */ -[[nodiscard]] inline meta_range resolve(const meta_ctx &ctx = locator::value_or()) noexcept { +[[nodiscard]] inline meta_range resolve(const meta_ctx &ctx) noexcept { auto &&context = internal::meta_context::from(ctx); - return {{context.value.cbegin(), ctx}, {context.value.cend(), ctx}}; + return {{ctx, context.value.cbegin()}, {ctx, context.value.cend()}}; +} + +/** + * @brief Returns a range to use to visit all meta types. + * @return An iterable range to use to visit all meta types. + */ +[[nodiscard]] inline meta_range resolve() noexcept { + return resolve(locator::value_or()); } /** * @brief Returns the meta type associated with a given identifier, if any. - * @param id Unique identifier. * @param ctx The context from which to search for meta types. + * @param id Unique identifier. * @return The meta type associated with the given identifier, if any. */ -[[nodiscard]] inline meta_type resolve(const id_type id, const meta_ctx &ctx = locator::value_or()) noexcept { +[[nodiscard]] inline meta_type resolve(const meta_ctx &ctx, const id_type id) noexcept { for(auto &&curr: resolve(ctx)) { if(curr.second.id() == id) { return curr.second; @@ -49,16 +67,34 @@ template return {}; } +/** + * @brief Returns the meta type associated with a given identifier, if any. + * @param id Unique identifier. + * @return The meta type associated with the given identifier, if any. + */ +[[nodiscard]] inline meta_type resolve(const id_type id) noexcept { + return resolve(locator::value_or(), id); +} + /** * @brief Returns the meta type associated with a given type info object. - * @param info The type info object of the requested type. * @param ctx The context from which to search for meta types. + * @param info The type info object of the requested type. * @return The meta type associated with the given type info object, if any. */ -[[nodiscard]] inline meta_type resolve(const type_info &info, const meta_ctx &ctx = locator::value_or()) noexcept { +[[nodiscard]] inline meta_type resolve(const meta_ctx &ctx, const type_info &info) noexcept { auto &&context = internal::meta_context::from(ctx); - const auto *elem = internal::try_resolve(info, context); - return elem ? meta_type{*elem, ctx} : meta_type{}; + const auto *elem = internal::try_resolve(context, info); + return elem ? meta_type{ctx, *elem} : meta_type{}; +} + +/** + * @brief Returns the meta type associated with a given type info object. + * @param info The type info object of the requested type. + * @return The meta type associated with the given type info object, if any. + */ +[[nodiscard]] inline meta_type resolve(const type_info &info) noexcept { + return resolve(locator::value_or(), info); } } // namespace entt diff --git a/src/entt/meta/utility.hpp b/src/entt/meta/utility.hpp index 479597623..c718668fe 100644 --- a/src/entt/meta/utility.hpp +++ b/src/entt/meta/utility.hpp @@ -156,7 +156,7 @@ using meta_function_helper_t = typename meta_function_helper::t * @return A meta any containing the returned value, if any. */ template -meta_any meta_dispatch([[maybe_unused]] Type &&value) { +std::enable_if_t, meta_any> meta_dispatch([[maybe_unused]] Type &&value) { if constexpr(std::is_same_v) { return meta_any{std::in_place_type}; } else if constexpr(std::is_same_v) { @@ -165,7 +165,6 @@ meta_any meta_dispatch([[maybe_unused]] Type &&value) { static_assert(std::is_lvalue_reference_v, "Invalid type"); return meta_any{std::in_place_type &>, std::as_const(value)}; } else { - static_assert(std::is_same_v, "Policy not supported"); return meta_any{std::forward(value)}; } } @@ -174,25 +173,37 @@ meta_any meta_dispatch([[maybe_unused]] Type &&value) { * @brief Returns the meta type of the i-th element of a list of arguments. * @tparam Type Type list of the actual types of arguments. * @param ctx The context from which to search for meta types. + * @param index The index of the element for which to return the meta type. * @return The meta type of the i-th element of the list of arguments. */ template -[[nodiscard]] static meta_type meta_arg(const std::size_t index, const meta_ctx &ctx = locator::value_or()) noexcept { +[[nodiscard]] static meta_type meta_arg(const meta_ctx &ctx, const std::size_t index) noexcept { auto &&context = internal::meta_context::from(ctx); - return {internal::meta_arg_node(Type{}, index, context), ctx}; + return {ctx, internal::meta_arg_node(context, Type{}, index)}; +} + +/** + * @brief Returns the meta type of the i-th element of a list of arguments. + * @tparam Type Type list of the actual types of arguments. + * @param index The index of the element for which to return the meta type. + * @return The meta type of the i-th element of the list of arguments. + */ +template +[[nodiscard]] static meta_type meta_arg(const std::size_t index) noexcept { + return meta_arg(locator::value_or(), index); } /** * @brief Sets the value of a given variable. * @tparam Type Reflected type to which the variable is associated. * @tparam Data The actual variable to set. + * @param ctx The context from which to search for meta types. * @param instance An opaque instance of the underlying type, if required. * @param value Parameter to use to set the variable. - * @param ctx The context from which to search for meta types. * @return True in case of success, false otherwise. */ template -[[nodiscard]] bool meta_setter([[maybe_unused]] meta_handle instance, [[maybe_unused]] meta_any value, const meta_ctx &ctx /*_TODO*/ = locator::value_or()) { +[[nodiscard]] bool meta_setter(const meta_ctx &ctx /*_TODO*/, [[maybe_unused]] meta_handle instance, [[maybe_unused]] meta_any value) { if constexpr(!std::is_same_v && !std::is_same_v) { if constexpr(std::is_member_function_pointer_v || std::is_function_v>>) { using descriptor = meta_function_helper_t; @@ -226,17 +237,30 @@ template return false; } +/** + * @brief Sets the value of a given variable. + * @tparam Type Reflected type to which the variable is associated. + * @tparam Data The actual variable to set. + * @param instance An opaque instance of the underlying type, if required. + * @param value Parameter to use to set the variable. + * @return True in case of success, false otherwise. + */ +template +[[nodiscard]] bool meta_setter([[maybe_unused]] meta_handle instance, [[maybe_unused]] meta_any value) { + return meta_setter(locator::value_or(), std::move(instance), std::move(value)); +} + /** * @brief Gets the value of a given variable. * @tparam Type Reflected type to which the variable is associated. * @tparam Data The actual variable to get. * @tparam Policy Optional policy (no policy set by default). - * @param instance An opaque instance of the underlying type, if required. * @param ctx The context from which to search for meta types. + * @param instance An opaque instance of the underlying type, if required. * @return A meta any containing the value of the underlying variable. */ template -[[nodiscard]] meta_any meta_getter([[maybe_unused]] meta_handle instance, const meta_ctx &ctx /*_TODO*/ = locator::value_or()) { +[[nodiscard]] std::enable_if_t, meta_any> meta_getter(const meta_ctx &ctx /*_TODO*/, [[maybe_unused]] meta_handle instance) { if constexpr(std::is_member_pointer_v || std::is_function_v>>) { if constexpr(!std::is_array_v>>>) { if constexpr(std::is_invocable_v) { @@ -264,6 +288,19 @@ template } } +/** + * @brief Gets the value of a given variable. + * @tparam Type Reflected type to which the variable is associated. + * @tparam Data The actual variable to get. + * @tparam Policy Optional policy (no policy set by default). + * @param instance An opaque instance of the underlying type, if required. + * @return A meta any containing the value of the underlying variable. + */ +template +[[nodiscard]] std::enable_if_t, meta_any> meta_getter([[maybe_unused]] meta_handle instance) { + return meta_getter(locator::value_or(), std::move(instance)); +} + /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. @@ -323,17 +360,47 @@ template * @tparam Type Reflected type to which the object to _invoke_ is associated. * @tparam Policy Optional policy (no policy set by default). * @tparam Candidate The type of the actual object to _invoke_. + * @param ctx The context from which to search for meta types. * @param instance An opaque instance of the underlying type, if required. * @param candidate The actual object to _invoke_. * @param args Parameters to use to _invoke_ the object. - * @param ctx The context from which to search for meta types. * @return A meta any containing the returned value, if any. */ template -[[nodiscard]] meta_any meta_invoke(meta_handle instance, Candidate &&candidate, meta_any *const args, const meta_ctx &ctx /*_TODO*/ = locator::value_or()) { +[[nodiscard]] std::enable_if_t, meta_any> meta_invoke(const meta_ctx &ctx, meta_handle instance, Candidate &&candidate, meta_any *const args) { return internal::meta_invoke(std::move(instance), std::forward(candidate), args, std::make_index_sequence>::args_type::size>{}); } +/** + * @brief Tries to _invoke_ an object given a list of erased parameters. + * @tparam Type Reflected type to which the object to _invoke_ is associated. + * @tparam Policy Optional policy (no policy set by default). + * @tparam Candidate The type of the actual object to _invoke_. + * @param instance An opaque instance of the underlying type, if required. + * @param candidate The actual object to _invoke_. + * @param args Parameters to use to _invoke_ the object. + * @return A meta any containing the returned value, if any. + */ +template +[[nodiscard]] std::enable_if_t, meta_any> meta_invoke(meta_handle instance, Candidate &&candidate, meta_any *const args) { + return meta_invoke(locator::value_or(), std::move(instance), std::forward(candidate), args); +} + +/** + * @brief Tries to invoke a function given a list of erased parameters. + * @tparam Type Reflected type to which the function is associated. + * @tparam Candidate The actual function to invoke. + * @tparam Policy Optional policy (no policy set by default). + * @param ctx The context from which to search for meta types. + * @param instance An opaque instance of the underlying type, if required. + * @param args Parameters to use to invoke the function. + * @return A meta any containing the returned value, if any. + */ +template +[[nodiscard]] std::enable_if_t, meta_any> meta_invoke(const meta_ctx &ctx /*_TODO*/, meta_handle instance, meta_any *const args) { + return internal::meta_invoke(std::move(instance), Candidate, args, std::make_index_sequence>::args_type::size>{}); +} + /** * @brief Tries to invoke a function given a list of erased parameters. * @tparam Type Reflected type to which the function is associated. @@ -341,12 +408,24 @@ template * @tparam Policy Optional policy (no policy set by default). * @param instance An opaque instance of the underlying type, if required. * @param args Parameters to use to invoke the function. - * @param ctx The context from which to search for meta types. * @return A meta any containing the returned value, if any. */ template -[[nodiscard]] meta_any meta_invoke(meta_handle instance, meta_any *const args, const meta_ctx &ctx /*_TODO*/ = locator::value_or()) { - return internal::meta_invoke(std::move(instance), Candidate, args, std::make_index_sequence>::args_type::size>{}); +[[nodiscard]] std::enable_if_t, meta_any> meta_invoke(meta_handle instance, meta_any *const args) { + return meta_invoke(locator::value_or(), std::move(instance), args); +} + +/** + * @brief Tries to construct an instance given a list of erased parameters. + * @tparam Type Actual type of the instance to construct. + * @tparam Args Types of arguments expected. + * @param ctx The context from which to search for meta types. + * @param args Parameters to use to construct the instance. + * @return A meta any containing the new instance, if any. + */ +template +[[nodiscard]] meta_any meta_construct(const meta_ctx &ctx /*_TODO*/, meta_any *const args) { + return internal::meta_construct(args, std::index_sequence_for{}); } /** @@ -354,12 +433,11 @@ template * @tparam Type Actual type of the instance to construct. * @tparam Args Types of arguments expected. * @param args Parameters to use to construct the instance. - * @param ctx The context from which to search for meta types. * @return A meta any containing the new instance, if any. */ template -[[nodiscard]] meta_any meta_construct(meta_any *const args, const meta_ctx &ctx /*_TODO*/ = locator::value_or()) { - return internal::meta_construct(args, std::index_sequence_for{}); +[[nodiscard]] meta_any meta_construct(meta_any *const args) { + return meta_construct(locator::value_or(), args); } /** @@ -367,13 +445,13 @@ template * @tparam Type Reflected type to which the object to _invoke_ is associated. * @tparam Policy Optional policy (no policy set by default). * @tparam Candidate The type of the actual object to _invoke_. + * @param ctx The context from which to search for meta types. * @param candidate The actual object to _invoke_. * @param args Parameters to use to _invoke_ the object. - * @param ctx The context from which to search for meta types. * @return A meta any containing the returned value, if any. */ template -[[nodiscard]] meta_any meta_construct(Candidate &&candidate, meta_any *const args, const meta_ctx &ctx /*_TODO*/ = locator::value_or()) { +[[nodiscard]] std::enable_if_t, meta_any> meta_construct(const meta_ctx &ctx /*_TODO*/, Candidate &&candidate, meta_any *const args) { if constexpr(meta_function_helper_t::is_static || std::is_class_v>>) { return internal::meta_invoke({}, std::forward(candidate), args, std::make_index_sequence>::args_type::size>{}); } else { @@ -381,18 +459,45 @@ template } } +/** + * @brief Tries to construct an instance given a list of erased parameters. + * @tparam Type Reflected type to which the object to _invoke_ is associated. + * @tparam Policy Optional policy (no policy set by default). + * @tparam Candidate The type of the actual object to _invoke_. + * @param candidate The actual object to _invoke_. + * @param args Parameters to use to _invoke_ the object. + * @return A meta any containing the returned value, if any. + */ +template +[[nodiscard]] std::enable_if_t, meta_any> meta_construct(Candidate &&candidate, meta_any *const args) { + return meta_construct(locator::value_or(), std::forward(candidate), args); +} + +/** + * @brief Tries to construct an instance given a list of erased parameters. + * @tparam Type Reflected type to which the function is associated. + * @tparam Candidate The actual function to invoke. + * @tparam Policy Optional policy (no policy set by default). + * @param ctx The context from which to search for meta types. + * @param args Parameters to use to invoke the function. + * @return A meta any containing the returned value, if any. + */ +template +[[nodiscard]] std::enable_if_t, meta_any> meta_construct(const meta_ctx &ctx /*_TODO*/, meta_any *const args) { + return meta_construct(ctx, Candidate, args); +} + /** * @brief Tries to construct an instance given a list of erased parameters. * @tparam Type Reflected type to which the function is associated. * @tparam Candidate The actual function to invoke. * @tparam Policy Optional policy (no policy set by default). * @param args Parameters to use to invoke the function. - * @param ctx The context from which to search for meta types. * @return A meta any containing the returned value, if any. */ template -[[nodiscard]] meta_any meta_construct(meta_any *const args, const meta_ctx &ctx /*_TODO*/ = locator::value_or()) { - return meta_construct(Candidate, args); +[[nodiscard]] std::enable_if_t, meta_any> meta_construct(meta_any *const args) { + return meta_construct(locator::value_or(), args); } } // namespace entt