Sfoglia il codice sorgente

meta: improved perf and compilation time, reduced loc

Michele Caini 6 anni fa
parent
commit
c57a7c745d
5 ha cambiato i file con 113 aggiunte e 346 eliminazioni
  1. 3 1
      TODO
  2. 4 4
      docs/md/meta.md
  3. 15 19
      src/entt/meta/factory.hpp
  4. 89 197
      src/entt/meta/meta.hpp
  5. 2 125
      test/entt/meta/meta.cpp

+ 3 - 1
TODO

@@ -37,4 +37,6 @@
 * is it possible to make named type constraints namespace-free?
 * stomp -> merge (naming is hard as heck, it's known thing)
 * observer: user defined filters (eg .replace<T, &function> or .group<T, U, &func>)
-* use meta_handle for inputs to invoke/ctor/...
+* any-of rule for views/groups (eg entity has A and any of B/C/D)
+* meta
+  - update doc

+ 4 - 4
docs/md/meta.md

@@ -417,10 +417,10 @@ There are a few alternatives available at the moment:
   ```
 
 * The _as-alias_ policy, associated with the type `entt::as_alias_t`.<br/>
-  It allows to build wrappers that act as aliases for the objects used to
-  initialize them. Modifying the object contained in the wrapper for which the
-  _aliasing_ was requested will make it possible to directly modify the instance
-  used to initialize the wrapper itself.<br/>
+  It allows to build wrappers that act as aliases for the objects that generated
+  them. Modifying the object contained in the wrapper for which the _aliasing_
+  was requested will make it possible to directly modify the instance used to
+  initialize the wrapper itself.<br/>
   This policy works with constructors (for example, when objects are taken from
   an external container rather than created on demand), data members and
   functions in general (as long as their return types are lvalue references).

+ 15 - 19
src/entt/meta/factory.hpp

@@ -86,7 +86,7 @@ meta_any construct(meta_any * const args, std::index_sequence<Indexes...>) {
 
 
 template<bool Const, typename Type, auto Data>
-bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index, [[maybe_unused]] meta_any value) {
+bool setter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any index, [[maybe_unused]] meta_any value) {
     bool accepted = false;
 
     if constexpr(!Const) {
@@ -94,7 +94,7 @@ bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index
             using helper_type = meta_function_helper_t<decltype(Data)>;
             using data_type = std::tuple_element_t<!std::is_member_function_pointer_v<decltype(Data)>, typename helper_type::args_type>;
             static_assert(std::is_invocable_v<decltype(Data), Type &, data_type>);
-            auto * const clazz = meta_any{handle}.try_cast<Type>();
+            auto * const clazz = instance.try_cast<Type>();
             auto * const direct = value.try_cast<data_type>();
 
             if(clazz && (direct || value.convert<data_type>())) {
@@ -104,7 +104,7 @@ bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index
         } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
             using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
             static_assert(std::is_invocable_v<decltype(Data), Type *>);
-            auto * const clazz = meta_any{handle}.try_cast<Type>();
+            auto * const clazz = instance.try_cast<Type>();
 
             if constexpr(std::is_array_v<data_type>) {
                 using underlying_type = std::remove_extent_t<data_type>;
@@ -152,7 +152,7 @@ bool setter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index
 
 
 template<typename Type, auto Data, typename Policy>
-meta_any getter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any index) {
+meta_any getter([[maybe_unused]] meta_any instance, [[maybe_unused]] meta_any index) {
     auto dispatch = [](auto &&value) {
         if constexpr(std::is_same_v<Policy, as_void_t>) {
             return meta_any{std::in_place_type<void>};
@@ -166,12 +166,12 @@ meta_any getter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any i
 
     if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>> || std::is_member_function_pointer_v<decltype(Data)>) {
         static_assert(std::is_invocable_v<decltype(Data), Type &>);
-        auto * const clazz = meta_any{handle}.try_cast<Type>();
+        auto * const clazz = instance.try_cast<Type>();
         return clazz ? dispatch(std::invoke(Data, *clazz)) : meta_any{};
     } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
         using data_type = std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>;
         static_assert(std::is_invocable_v<decltype(Data), Type *>);
-        auto * const clazz = meta_any{handle}.try_cast<Type>();
+        auto * const clazz = instance.try_cast<Type>();
 
         if constexpr(std::is_array_v<data_type>) {
             auto * const idx = index.try_cast<std::size_t>();
@@ -193,7 +193,7 @@ meta_any getter([[maybe_unused]] meta_handle handle, [[maybe_unused]] meta_any i
 
 
 template<typename Type, auto Candidate, typename Policy, std::size_t... Indexes>
-meta_any invoke([[maybe_unused]] meta_handle handle, meta_any *args, std::index_sequence<Indexes...>) {
+meta_any invoke([[maybe_unused]] meta_any instance, meta_any *args, std::index_sequence<Indexes...>) {
     using helper_type = meta_function_helper_t<decltype(Candidate)>;
 
     auto dispatch = [](auto *... params) {
@@ -221,7 +221,7 @@ meta_any invoke([[maybe_unused]] meta_handle handle, meta_any *args, std::index_
     if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Candidate)>>>) {
         return (std::get<Indexes>(direct) && ...) ? dispatch(std::get<Indexes>(direct)...) : meta_any{};
     } else {
-        auto * const clazz = meta_any{handle}.try_cast<Type>();
+        auto * const clazz = instance.try_cast<Type>();
         return (clazz && (std::get<Indexes>(direct) && ...)) ? dispatch(clazz, std::get<Indexes>(direct)...) : meta_any{};
     }
 }
@@ -604,14 +604,10 @@ public:
 
         static internal::meta_dtor_node node{
             type,
-            [](meta_handle handle) {
-                const auto valid = (handle.type() == internal::meta_info<Type>::resolve());
-
-                if(valid) {
-                    std::invoke(Func, *meta_any{handle}.try_cast<Type>());
+            [](void *instance) {
+                if(instance) {
+                    std::invoke(Func, *static_cast<Type *>(instance));
                 }
-
-                return valid;
             }
         };
 
@@ -650,8 +646,8 @@ public:
                 true,
                 true,
                 &internal::meta_info<Type>::resolve,
-                [](meta_handle, meta_any, meta_any) { return false; },
-                [](meta_handle, meta_any) -> meta_any { return Data; }
+                [](meta_any, meta_any, meta_any) { return false; },
+                [](meta_any, meta_any) -> meta_any { return Data; }
             };
 
             curr = &node;
@@ -774,8 +770,8 @@ public:
             !std::is_member_function_pointer_v<decltype(Candidate)>,
             &internal::meta_info<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, typename helper_type::return_type>>::resolve,
             &helper_type::arg,
-            [](meta_handle handle, meta_any *any) {
-                return internal::invoke<Type, Candidate, Policy>(handle, any, helper_type::index_sequence);
+            [](meta_any instance, meta_any *args) {
+                return internal::invoke<Type, Candidate, Policy>(std::move(instance), args, helper_type::index_sequence);
             }
         };
 

+ 89 - 197
src/entt/meta/meta.hpp

@@ -2,9 +2,9 @@
 #define ENTT_META_META_HPP
 
 
-#include <array>
 #include <cstddef>
 #include <utility>
+#include <functional>
 #include <type_traits>
 #include "../config/config.h"
 #include "../core/type_traits.hpp"
@@ -15,7 +15,6 @@ namespace entt {
 
 
 class meta_any;
-class meta_handle;
 class meta_type;
 
 
@@ -67,7 +66,7 @@ struct meta_ctor_node {
 
 struct meta_dtor_node {
     meta_type_node * const parent;
-    bool(* const invoke)(meta_handle);
+    void(* const invoke)(void *);
 };
 
 
@@ -79,8 +78,8 @@ struct meta_data_node {
     const bool is_const;
     const bool is_static;
     meta_type_node *(* const type)() ENTT_NOEXCEPT;
-    bool(* const set)(meta_handle, meta_any, meta_any);
-    meta_any(* const get)(meta_handle, meta_any);
+    bool(* const set)(meta_any, meta_any, meta_any);
+    meta_any(* const get)(meta_any, meta_any);
 };
 
 
@@ -95,7 +94,7 @@ struct meta_func_node {
     const bool is_static;
     meta_type_node *(* const ret)() ENTT_NOEXCEPT;
     meta_type_node *(* const arg)(size_type) ENTT_NOEXCEPT;
-    meta_any(* const invoke)(meta_handle, meta_any *);
+    meta_any(* const invoke)(meta_any, meta_any *);
 };
 
 
@@ -303,9 +302,6 @@ struct meta_info: meta_node<std::remove_cv_t<std::remove_reference_t<Type>>...>
  * constructible.
  */
 class meta_any {
-    /*! @brief A meta handle is allowed to _inherit_ from a meta any. */
-    friend class meta_handle;
-
     using storage_type = std::aligned_storage_t<sizeof(void *), alignof(void *)>;
     using copy_fn_type = void(meta_any &, const meta_any &);
     using steal_fn_type = void(meta_any &, meta_any &);
@@ -321,9 +317,8 @@ class meta_any {
 
         static void destroy(meta_any &any) {
             const auto * const node = internal::meta_info<Type>::resolve();
-            [[maybe_unused]] const bool destroyed = (!node->dtor || node->dtor->invoke(any));
+            if(node->dtor) { node->dtor->invoke(any.instance); }
             delete static_cast<Type *>(any.instance);
-            ENTT_ASSERT(destroyed);
         }
 
         static void copy(meta_any &to, const meta_any &from) {
@@ -347,9 +342,8 @@ class meta_any {
 
         static void destroy(meta_any &any) {
             const auto * const node = internal::meta_info<Type>::resolve();
-            [[maybe_unused]] const bool destroyed = (!node->dtor || node->dtor->invoke(any));
+            if(node->dtor) { node->dtor->invoke(any.instance); }
             static_cast<Type *>(any.instance)->~Type();
-            ENTT_ASSERT(destroyed);
         }
 
         static void copy(meta_any &to, const meta_any &from) {
@@ -362,6 +356,13 @@ class meta_any {
         }
     };
 
+    meta_any(const internal::meta_type_node *curr, void *ref) ENTT_NOEXCEPT
+        : meta_any{}
+    {
+        node = curr;
+        instance = ref;
+    }
+
 public:
     /*! @brief Default constructor. */
     meta_any() ENTT_NOEXCEPT = default;
@@ -391,30 +392,21 @@ public:
     /**
      * @brief Constructs a meta any that holds an unmanaged object.
      * @tparam Type Type of object to use to initialize the container.
-     * @param type An instance of an object to use to initialize the container.
+     * @param value An instance of an object to use to initialize the container.
      */
     template<typename Type>
-    explicit meta_any(std::reference_wrapper<Type> type)
-        : meta_any{}
-    {
-        node = internal::meta_info<Type>::resolve();
-        instance = &type.get();
-    }
-
-    /**
-     * @brief Constructs a meta any from a meta handle object.
-     * @param handle A reference to an object to use to initialize the meta any.
-     */
-    inline meta_any(meta_handle handle) ENTT_NOEXCEPT;
+    meta_any(std::reference_wrapper<Type> value)
+        : meta_any{internal::meta_info<Type>::resolve(), &value.get()}
+    {}
 
     /**
      * @brief Constructs a meta any from a given value.
      * @tparam Type Type of object to use to initialize the container.
-     * @param type An instance of an object to use to initialize the container.
+     * @param value An instance of an object to use to initialize the container.
      */
     template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_any>>>
-    meta_any(Type &&type)
-        : meta_any{std::in_place_type<std::remove_cv_t<std::remove_reference_t<Type>>>, std::forward<Type>(type)}
+    meta_any(Type &&value)
+        : meta_any{std::in_place_type<std::remove_cv_t<std::remove_reference_t<Type>>>, std::forward<Type>(value)}
     {}
 
     /**
@@ -455,12 +447,12 @@ public:
     /**
      * @brief Assignment operator.
      * @tparam Type Type of object to use to initialize the container.
-     * @param type An instance of an object to use to initialize the container.
+     * @param value An instance of an object to use to initialize the container.
      * @return This meta any object.
      */
     template<typename Type>
-    meta_any & operator=(Type &&type) {
-        return (*this = meta_any{std::forward<Type>(type)});
+    meta_any & operator=(Type &&value) {
+        return (*this = meta_any{std::forward<Type>(value)});
     }
 
     /**
@@ -592,6 +584,14 @@ public:
         *this = meta_any{std::in_place_type_t<Type>{}, std::forward<Args>(args)...};
     }
 
+    /**
+     * @brief Indirection operator for aliasing construction.
+     * @return An alias to the contained object.
+     */
+    meta_any operator *() const ENTT_NOEXCEPT {
+        return meta_any{node, instance};
+    }
+
     /**
      * @brief Returns false if a container is empty, true otherwise.
      * @return False if the container is empty, true otherwise.
@@ -649,62 +649,37 @@ private:
  * @brief Opaque pointers to instances of any type.
  *
  * A handle doesn't perform copies and isn't responsible for the contained
- * object. It doesn't prolong the lifetime of the pointed instance. Users are
- * responsible for ensuring that the target object remains alive for the entire
- * interval of use of the handle.
+ * object. It doesn't prolong the lifetime of the pointed instance.<br/>
+ * Handles are used mainly to gnerate aliases for actual objects when needed.
  */
-class meta_handle {
-    /*! @brief A meta any is allowed to _inherit_ from a meta handle. */
-    friend class meta_any;
-
-public:
+struct meta_handle {
     /*! @brief Default constructor. */
-    meta_handle() ENTT_NOEXCEPT = default;
-
-    /**
-     * @brief Constructs a meta handle from a meta any object.
-     * @param any A reference to an object to use to initialize the handle.
-     */
-    meta_handle(meta_any &any) ENTT_NOEXCEPT
-        : node{any.node},
-          instance{any.instance}
-    {}
+    meta_handle() = default;
 
     /**
-     * @brief Constructs a meta handle from a given instance.
-     * @tparam Type Type of object to use to initialize the handle.
-     * @param obj A reference to an object to use to initialize the handle.
+     * @brief Creates an alias for the actual object.
+     * @tparam Type Type of object to use to initialize the container.
+     * @param value An instance of an object to use to initialize the container.
      */
-    template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_handle>>>
-    meta_handle(Type &obj) ENTT_NOEXCEPT
-        : node{internal::meta_info<Type>::resolve()},
-          instance{&obj}
-    {}
-
-    /*! @copydoc meta_any::type */
-    inline meta_type type() const ENTT_NOEXCEPT;
-
-    /*! @copydoc meta_any::data */
-    const void * data() const ENTT_NOEXCEPT {
-        return instance;
-    }
-
-    /*! @copydoc data */
-    void * data() ENTT_NOEXCEPT {
-        return const_cast<void *>(std::as_const(*this).data());
+    template<typename Type>
+    meta_handle(Type &&value) ENTT_NOEXCEPT
+        : meta_handle{}
+    {
+        if constexpr(std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_any>) {
+            any = *value;
+        } else {
+            static_assert(std::is_lvalue_reference_v<Type>);
+            any = std::ref(value);
+        }
     }
 
-    /**
-     * @brief Returns false if a handle is empty, true otherwise.
-     * @return False if the handle is empty, true otherwise.
-     */
-    explicit operator bool() const ENTT_NOEXCEPT {
-        return instance;
+    /*! @copydoc meta_any::operator* */
+    meta_any operator *() const {
+        return any;
     }
 
 private:
-    const internal::meta_type_node *node;
-    void *instance;
+    meta_any any;
 };
 
 
@@ -914,9 +889,13 @@ struct meta_ctor {
      * @return A meta any containing the new instance, if any.
      */
     template<typename... Args>
-    meta_any invoke(Args &&... args) const {
-        std::array<meta_any, sizeof...(Args)> arguments{{std::forward<Args>(args)...}};
-        return sizeof...(Args) == size() ? node->invoke(arguments.data()) : meta_any{};
+    meta_any invoke([[maybe_unused]] Args &&... args) const {
+        if constexpr(sizeof...(Args) == 0) {
+            return sizeof...(Args) == size() ? node->invoke(nullptr) : meta_any{};
+        } else {
+            meta_any arguments[]{std::forward<Args>(args)...};
+            return sizeof...(Args) == size() ? node->invoke(arguments) : meta_any{};
+        }
     }
 
     /**
@@ -965,54 +944,6 @@ inline bool operator!=(const meta_ctor &lhs, const meta_ctor &rhs) ENTT_NOEXCEPT
 }
 
 
-/*! @brief Opaque container for meta destructors. */
-struct meta_dtor {
-    /*! @copydoc meta_prop::meta_prop */
-    meta_dtor(const internal::meta_dtor_node *curr = nullptr) ENTT_NOEXCEPT
-        : node{curr}
-    {}
-
-    /*! @copydoc meta_base::parent */
-    inline meta_type parent() const ENTT_NOEXCEPT;
-
-    /**
-     * @brief Destroys an instance of the underlying type.
-     *
-     * It must be possible to cast the instance to the parent type of the meta
-     * destructor. Otherwise, invoking the meta destructor results in an
-     * undefined behavior.
-     *
-     * @param handle An opaque pointer to an instance of the underlying type.
-     * @return True in case of success, false otherwise.
-     */
-    bool invoke(meta_handle handle) const {
-        return node->invoke(handle);
-    }
-
-    /**
-     * @brief Returns true if a meta object is valid, false otherwise.
-     * @return True if the meta object is valid, false otherwise.
-     */
-    explicit operator bool() const ENTT_NOEXCEPT {
-        return node;
-    }
-
-    /*! @copydoc meta_prop::operator== */
-    bool operator==(const meta_dtor &other) const ENTT_NOEXCEPT {
-        return node == other.node;
-    }
-
-private:
-    const internal::meta_dtor_node *node;
-};
-
-
-/*! @copydoc operator!=(const meta_prop &, const meta_prop &) */
-inline bool operator!=(const meta_dtor &lhs, const meta_dtor &rhs) ENTT_NOEXCEPT {
-    return !(lhs == rhs);
-}
-
-
 /*! @brief Opaque container for meta data. */
 struct meta_data {
     /*! @copydoc meta_prop::meta_prop */
@@ -1057,13 +988,13 @@ struct meta_data {
      * of the variable is possible. Otherwise, invoking the setter does nothing.
      *
      * @tparam Type Type of value to assign.
-     * @param handle An opaque pointer to an instance of the underlying type.
+     * @param instance An opaque instance of the underlying type.
      * @param value Parameter to use to set the underlying variable.
      * @return True in case of success, false otherwise.
      */
     template<typename Type>
-    bool set(meta_handle handle, Type &&value) const {
-        return node->set(handle, meta_any{}, std::forward<Type>(value));
+    bool set(meta_handle instance, Type &&value) const {
+        return node->set(*instance, {}, std::forward<Type>(value));
     }
 
     /**
@@ -1076,15 +1007,15 @@ struct meta_data {
      * type is possible. Otherwise, invoking the setter does nothing.
      *
      * @tparam Type Type of value to assign.
-     * @param handle An opaque pointer to an instance of the underlying type.
+     * @param instance An opaque instance of the underlying type.
      * @param index Position of the underlying element to set.
      * @param value Parameter to use to set the underlying element.
      * @return True in case of success, false otherwise.
      */
     template<typename Type>
-    bool set(meta_handle handle, std::size_t index, Type &&value) const {
+    bool set(meta_handle instance, std::size_t index, Type &&value) const {
         ENTT_ASSERT(index < node->type()->extent);
-        return node->set(handle, index, std::forward<Type>(value));
+        return node->set(*instance, index, std::forward<Type>(value));
     }
 
     /**
@@ -1093,11 +1024,11 @@ struct meta_data {
      * It must be possible to cast the instance to the parent type of the meta
      * data. Otherwise, invoking the getter results in an undefined behavior.
      *
-     * @param handle An opaque pointer to an instance of the underlying type.
+     * @param instance An opaque instance of the underlying type.
      * @return A meta any containing the value of the underlying variable.
      */
-    meta_any get(meta_handle handle) const {
-        return node->get(handle, meta_any{});
+    meta_any get(meta_handle instance) const {
+        return node->get(*instance, {});
     }
 
     /**
@@ -1106,13 +1037,13 @@ struct meta_data {
      * It must be possible to cast the instance to the parent type of the meta
      * data. Otherwise, invoking the getter results in an undefined behavior.
      *
-     * @param handle An opaque pointer to an instance of the underlying type.
+     * @param instance An opaque instance of the underlying type.
      * @param index Position of the underlying element to get.
      * @return A meta any containing the value of the underlying element.
      */
-    meta_any get(meta_handle handle, std::size_t index) const {
+    meta_any get(meta_handle instance, std::size_t index) const {
         ENTT_ASSERT(index < node->type()->extent);
-        return node->get(handle, index);
+        return node->get(*instance, index);
     }
 
     /**
@@ -1227,15 +1158,14 @@ struct meta_func {
      * undefined behavior.
      *
      * @tparam Args Types of arguments to use to invoke the function.
-     * @param handle An opaque pointer to an instance of the underlying type.
+     * @param instance An opaque instance of the underlying type.
      * @param args Parameters to use to invoke the function.
      * @return A meta any containing the returned value, if any.
      */
     template<typename... Args>
-    meta_any invoke(meta_handle handle, Args &&... args) const {
-        // makes aliasing on the values and passes forward references if any
-        std::array<meta_any, sizeof...(Args)> arguments{{meta_handle{args}...}};
-        return sizeof...(Args) == size() ? node->invoke(handle, arguments.data()) : meta_any{};
+    meta_any invoke(meta_handle instance, Args &&... args) const {
+        meta_any arguments[]{*instance, std::forward<Args>(args)...};
+        return sizeof...(Args) == size() ? node->invoke(arguments[0], &arguments[sizeof...(Args) != 0]) : meta_any{};
     }
 
     /**
@@ -1504,14 +1434,6 @@ public:
         return ctor<Args...>(std::index_sequence_for<Args...>{});
     }
 
-    /**
-     * @brief Returns the meta destructor associated with a given type.
-     * @return The meta destructor associated with the given type, if any.
-     */
-    meta_dtor dtor() const ENTT_NOEXCEPT {
-        return node->dtor;
-    }
-
     /**
      * @brief Iterates all the meta data of a meta type.
      *
@@ -1581,34 +1503,22 @@ public:
      */
     template<typename... Args>
     meta_any construct(Args &&... args) const {
-        std::array<meta_any, sizeof...(Args)> arguments{{std::forward<Args>(args)...}};
-        meta_any any{};
+        auto construct_if = [this](auto *params) {
+            meta_any any{};
 
-        internal::find_if<&internal::meta_type_node::ctor>([data = arguments.data(), &any](const auto *curr) {
-            if(curr->size == sizeof...(args)) {
-                any = curr->invoke(data);
-            }
-
-            return static_cast<bool>(any);
-        }, node);
+            internal::find_if<&internal::meta_type_node::ctor>([params, &any](const auto *curr) {
+                return (curr->size == sizeof...(args)) && (any = curr->invoke(params));
+            }, node);
 
-        return any;
-    }
+            return any;
+        };
 
-    /**
-     * @brief Destroys an instance of the underlying type.
-     *
-     * It must be possible to cast the instance to the underlying type.
-     * Otherwise, invoking the meta destructor results in an undefined
-     * behavior.<br/>
-     * If no destructor has been set, this function returns true without doing
-     * anything.
-     *
-     * @param handle An opaque pointer to an instance of the underlying type.
-     * @return True in case of success, false otherwise.
-     */
-    bool destroy(meta_handle handle) const {
-        return (handle.type() == node) && (!node->dtor || node->dtor->invoke(handle));
+        if constexpr(sizeof...(Args) == 0) {
+            return construct_if(nullptr);
+        } else {
+            meta_any arguments[]{std::forward<Args>(args)...};
+            return construct_if(arguments);
+        }
     }
 
     /**
@@ -1678,24 +1588,11 @@ inline bool operator!=(const meta_type &lhs, const meta_type &rhs) ENTT_NOEXCEPT
 }
 
 
-inline meta_any::meta_any(meta_handle handle) ENTT_NOEXCEPT
-    : meta_any{}
-{
-    node = handle.node;
-    instance = handle.instance;
-}
-
-
 inline meta_type meta_any::type() const ENTT_NOEXCEPT {
     return node;
 }
 
 
-inline meta_type meta_handle::type() const ENTT_NOEXCEPT {
-    return node;
-}
-
-
 inline meta_type meta_base::parent() const ENTT_NOEXCEPT {
     return node->parent;
 }
@@ -1726,11 +1623,6 @@ inline meta_type meta_ctor::arg(size_type index) const ENTT_NOEXCEPT {
 }
 
 
-inline meta_type meta_dtor::parent() const ENTT_NOEXCEPT {
-    return node->parent;
-}
-
-
 inline meta_type meta_data::parent() const ENTT_NOEXCEPT {
     return node->parent;
 }

+ 2 - 125
test/entt/meta/meta.cpp

@@ -289,22 +289,6 @@ TEST_F(Meta, Resolve) {
     ASSERT_TRUE(found);
 }
 
-TEST_F(Meta, MetaAnyFromMetaHandle) {
-    int value = 42;
-    entt::meta_handle handle{value};
-    entt::meta_any any{handle};
-    any.cast<int>() = 3;
-
-    ASSERT_TRUE(any);
-    ASSERT_EQ(any.type(), entt::resolve<int>());
-    ASSERT_EQ(any.try_cast<std::size_t>(), nullptr);
-    ASSERT_EQ(any.try_cast<int>(), handle.data());
-    ASSERT_EQ(std::as_const(any).try_cast<int>(), handle.data());
-    ASSERT_EQ(any.data(), handle.data());
-    ASSERT_EQ(std::as_const(any).data(), handle.data());
-    ASSERT_EQ(value, 3);
-}
-
 TEST_F(Meta, MetaAnySBO) {
     entt::meta_any any{'c'};
 
@@ -901,35 +885,6 @@ TEST_F(Meta, MetaAnyConstConvert) {
     ASSERT_EQ(other.cast<int>(), 42);
 }
 
-TEST_F(Meta, MetaHandleFromObject) {
-    empty_type empty{};
-    entt::meta_handle handle{empty};
-
-    ASSERT_TRUE(handle);
-    ASSERT_EQ(handle.type(), entt::resolve<empty_type>());
-    ASSERT_EQ(std::as_const(handle).data(), &empty);
-    ASSERT_EQ(handle.data(), &empty);
-}
-
-TEST_F(Meta, MetaHandleFromMetaAny) {
-    entt::meta_any any{42};
-    entt::meta_handle handle{any};
-
-    ASSERT_TRUE(handle);
-    ASSERT_EQ(handle.type(), entt::resolve<int>());
-    ASSERT_EQ(std::as_const(handle).data(), any.data());
-    ASSERT_EQ(handle.data(), any.data());
-}
-
-TEST_F(Meta, MetaHandleEmpty) {
-    entt::meta_handle handle{};
-
-    ASSERT_FALSE(handle);
-    ASSERT_FALSE(handle.type());
-    ASSERT_EQ(std::as_const(handle).data(), nullptr);
-    ASSERT_EQ(handle.data(), nullptr);
-}
-
 TEST_F(Meta, MetaProp) {
     auto prop = entt::resolve<char>().prop(props::prop_int);
 
@@ -1118,33 +1073,6 @@ TEST_F(Meta, MetaCtorFuncCastAndConvert) {
     ASSERT_EQ(any.cast<derived_type>().c, 'c');
 }
 
-TEST_F(Meta, MetaDtor) {
-    auto dtor = entt::resolve<empty_type>().dtor();
-    empty_type empty{};
-
-    ASSERT_TRUE(dtor);
-    ASSERT_NE(dtor, entt::meta_dtor{});
-    ASSERT_EQ(dtor.parent(), entt::resolve("empty"_hs));
-    ASSERT_EQ(empty_type::counter, 0);
-    ASSERT_TRUE(dtor.invoke(empty));
-    ASSERT_EQ(empty_type::counter, 1);
-}
-
-TEST_F(Meta, MetaDtorMetaAnyArg) {
-    auto dtor = entt::resolve<empty_type>().dtor();
-    entt::meta_any any{empty_type{}};
-
-    ASSERT_EQ(empty_type::counter, 0);
-    ASSERT_TRUE(dtor.invoke(any));
-    ASSERT_EQ(empty_type::counter, 1);
-}
-
-TEST_F(Meta, MetaDtorMetaAnyInvalidArg) {
-    auto instance = 0;
-    ASSERT_FALSE(entt::resolve<empty_type>().dtor().invoke(instance));
-}
-
-
 TEST_F(Meta, MetaData) {
     auto data = entt::resolve<data_type>().data("i"_hs);
     data_type instance{};
@@ -1690,8 +1618,8 @@ TEST_F(Meta, MetaFuncByReference) {
     entt::meta_any any{3};
     int value = 4;
 
-    ASSERT_EQ(func.invoke({}, value).cast<int>(), 8);
-    ASSERT_EQ(func.invoke({}, any).cast<int>(), 6);
+    ASSERT_EQ(func.invoke({}, std::ref(value)).cast<int>(), 8);
+    ASSERT_EQ(func.invoke({}, *any).cast<int>(), 6);
     ASSERT_EQ(any.cast<int>(), 6);
     ASSERT_EQ(value, 8);
 }
@@ -1786,11 +1714,6 @@ TEST_F(Meta, MetaTypeCtor) {
     ASSERT_TRUE((type.ctor<const derived_type &, double>()));
 }
 
-TEST_F(Meta, MetaTypeDtor) {
-    ASSERT_TRUE(entt::resolve<fat_type>().dtor());
-    ASSERT_FALSE(entt::resolve<int>().dtor());
-}
-
 TEST_F(Meta, MetaTypeData) {
     auto type = entt::resolve<data_type>();
     int counter{};
@@ -1857,52 +1780,6 @@ TEST_F(Meta, MetaTypeConstructCastAndConvert) {
     ASSERT_EQ(any.cast<derived_type>().c, 'c');
 }
 
-TEST_F(Meta, MetaTypeDestroyDtor) {
-    auto type = entt::resolve<empty_type>();
-    empty_type instance;
-
-    ASSERT_EQ(empty_type::counter, 0);
-    ASSERT_TRUE(type.destroy(instance));
-    ASSERT_EQ(empty_type::counter, 1);
-}
-
-TEST_F(Meta, MetaTypeDestroyDtorInvalidArg) {
-    auto type = entt::resolve<empty_type>();
-    auto instance = 'c';
-
-    ASSERT_EQ(empty_type::counter, 0);
-    ASSERT_FALSE(type.destroy(instance));
-    ASSERT_EQ(empty_type::counter, 0);
-}
-
-TEST_F(Meta, MetaTypeDestroyDtorCastAndConvert) {
-    auto type = entt::resolve<empty_type>();
-    fat_type instance{};
-
-    ASSERT_EQ(empty_type::counter, 0);
-    ASSERT_FALSE(type.destroy(instance));
-    ASSERT_EQ(empty_type::counter, 0);
-}
-
-TEST_F(Meta, MetaTypeDestroyNoDtor) {
-    auto instance = 'c';
-    ASSERT_TRUE(entt::resolve<char>().destroy(instance));
-}
-
-TEST_F(Meta, MetaTypeDestroyNoDtorInvalidArg) {
-    auto instance = 42;
-    ASSERT_FALSE(entt::resolve<char>().destroy(instance));
-}
-
-TEST_F(Meta, MetaTypeDestroyNoDtorVoid) {
-    ASSERT_FALSE(entt::resolve<void>().destroy({}));
-}
-
-TEST_F(Meta, MetaTypeDestroyNoDtorCastAndConvert) {
-    auto instance = 42.;
-    ASSERT_FALSE(entt::resolve<int>().destroy(instance));
-}
-
 TEST_F(Meta, MetaDataFromBase) {
     auto type = entt::resolve<concrete_type>();
     concrete_type instance;