Browse Source

meta: move the meta context argument to the first slot of the argument lists

Michele Caini 3 years ago
parent
commit
34abddfbbd

+ 83 - 25
src/entt/meta/factory.hpp

@@ -29,7 +29,7 @@ namespace entt {
 
 
 namespace internal {
 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);
     auto &&context = internal::meta_context::from(ctx);
     ENTT_ASSERT(context.value.contains(info.hash()), "Type not available");
     ENTT_ASSERT(context.value.contains(info.hash()), "Type not available");
     return context.value[info.hash()];
     return context.value[info.hash()];
@@ -96,7 +96,7 @@ class meta_factory {
         static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
         static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
 
 
         auto &&elem = internal::meta_extend(
         auto &&elem = internal::meta_extend(
-            internal::owner(*info, *ctx),
+            internal::owner(*ctx, *info),
             id,
             id,
             internal::meta_data_node{
             internal::meta_data_node{
                 /* this is never static */
                 /* this is never static */
@@ -104,7 +104,7 @@ class meta_factory {
                 Setter::size,
                 Setter::size,
                 &internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>,
                 &internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>,
                 &meta_arg<type_list<type_list_element_t<type_list_element_t<Index, args_type>::size != 1u, type_list_element_t<Index, args_type>>...>>,
                 &meta_arg<type_list<type_list_element_t<type_list_element_t<Index, args_type>::size != 1u, type_list_element_t<Index, args_type>>...>>,
-                +[](meta_handle instance, meta_any value, const meta_ctx &area) { return (meta_setter<Type, value_list_element_v<Index, Setter>>(*instance.operator->(), value.as_ref(), area) || ...); },
+                +[](const meta_ctx &area, meta_handle instance, meta_any value) { return (meta_setter<Type, value_list_element_v<Index, Setter>>(area, *instance.operator->(), value.as_ref()) || ...); },
                 &meta_getter<Type, Getter, Policy>});
                 &meta_getter<Type, Getter, Policy>});
 
 
         bucket = &elem.prop;
         bucket = &elem.prop;
@@ -123,7 +123,7 @@ public:
         : ctx{&area},
         : ctx{&area},
           bucket{},
           bucket{},
           info{&type_id<Type>()} {
           info{&type_id<Type>()} {
-        auto &&elem = internal::owner(*info, *ctx);
+        auto &&elem = internal::owner(*ctx, *info);
 
 
         if(!elem.details) {
         if(!elem.details) {
             elem.details = std::make_shared<internal::meta_type_descriptor>();
             elem.details = std::make_shared<internal::meta_type_descriptor>();
@@ -138,8 +138,8 @@ public:
      * @return An extended meta factory for the given type.
      * @return An extended meta factory for the given type.
      */
      */
     auto type(const id_type id) noexcept {
     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;
         bucket = &elem.details->prop;
         elem.id = id;
         elem.id = id;
         return *this;
         return *this;
@@ -158,7 +158,7 @@ public:
         static_assert(!std::is_same_v<Type, Base> && std::is_base_of_v<Base, Type>, "Invalid base type");
         static_assert(!std::is_same_v<Type, Base> && std::is_base_of_v<Base, Type>, "Invalid base type");
 
 
         internal::meta_extend(
         internal::meta_extend(
-            internal::owner(*info, *ctx),
+            internal::owner(*ctx, *info),
             type_id<Base>().hash(),
             type_id<Base>().hash(),
             internal::meta_base_node{
             internal::meta_base_node{
                 &internal::resolve<Base>,
                 &internal::resolve<Base>,
@@ -187,11 +187,11 @@ public:
         using conv_type = std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<decltype(Candidate), Type &>>>;
         using conv_type = std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<decltype(Candidate), Type &>>>;
 
 
         internal::meta_extend(
         internal::meta_extend(
-            internal::owner(*info, *ctx),
+            internal::owner(*ctx, *info),
             type_id<conv_type>().hash(),
             type_id<conv_type>().hash(),
             internal::meta_conv_node{
             internal::meta_conv_node{
-                +[](const void *instance, const meta_ctx &area) {
-                    return forward_as_meta(std::invoke(Candidate, *static_cast<const Type *>(instance)), area);
+                +[](const meta_ctx &area, const void *instance) {
+                    return forward_as_meta(area, std::invoke(Candidate, *static_cast<const Type *>(instance)));
                 }});
                 }});
 
 
         bucket = nullptr;
         bucket = nullptr;
@@ -212,11 +212,11 @@ public:
         using conv_type = std::remove_cv_t<std::remove_reference_t<To>>;
         using conv_type = std::remove_cv_t<std::remove_reference_t<To>>;
 
 
         internal::meta_extend(
         internal::meta_extend(
-            internal::owner(*info, *ctx),
+            internal::owner(*ctx, *info),
             type_id<conv_type>().hash(),
             type_id<conv_type>().hash(),
             internal::meta_conv_node{
             internal::meta_conv_node{
-                +[](const void *instance, const meta_ctx &area) {
-                    return forward_as_meta(static_cast<To>(*static_cast<const Type *>(instance)), area);
+                +[](const meta_ctx &area, const void *instance) {
+                    return forward_as_meta(area, static_cast<To>(*static_cast<const Type *>(instance)));
                 }});
                 }});
 
 
         bucket = nullptr;
         bucket = nullptr;
@@ -239,11 +239,12 @@ public:
     template<auto Candidate, typename Policy = as_is_t>
     template<auto Candidate, typename Policy = as_is_t>
     auto ctor() noexcept {
     auto ctor() noexcept {
         using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
         using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
+        static_assert(std::is_base_of_v<meta_policy, Policy>, "Unknown policy type");
         static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy");
         static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy");
         static_assert(std::is_same_v<std::remove_cv_t<std::remove_reference_t<typename descriptor::return_type>>, Type>, "The function doesn't return an object of the required type");
         static_assert(std::is_same_v<std::remove_cv_t<std::remove_reference_t<typename descriptor::return_type>>, Type>, "The function doesn't return an object of the required type");
 
 
         internal::meta_extend(
         internal::meta_extend(
-            internal::owner(*info, *ctx),
+            internal::owner(*ctx, *info),
             type_id<typename descriptor::args_type>().hash(),
             type_id<typename descriptor::args_type>().hash(),
             internal::meta_ctor_node{
             internal::meta_ctor_node{
                 descriptor::args_type::size,
                 descriptor::args_type::size,
@@ -269,7 +270,7 @@ public:
         using descriptor = meta_function_helper_t<Type, Type (*)(Args...)>;
         using descriptor = meta_function_helper_t<Type, Type (*)(Args...)>;
 
 
         internal::meta_extend(
         internal::meta_extend(
-            internal::owner(*info, *ctx),
+            internal::owner(*ctx, *info),
             type_id<typename descriptor::args_type>().hash(),
             type_id<typename descriptor::args_type>().hash(),
             internal::meta_ctor_node{
             internal::meta_ctor_node{
                 descriptor::args_type::size,
                 descriptor::args_type::size,
@@ -303,7 +304,7 @@ public:
         static_assert(std::is_invocable_v<decltype(Func), Type &>, "The function doesn't accept an object of the type provided");
         static_assert(std::is_invocable_v<decltype(Func), Type &>, "The function doesn't accept an object of the type provided");
 
 
         internal::meta_extend(
         internal::meta_extend(
-            internal::owner(*info, *ctx),
+            internal::owner(*ctx, *info),
             internal::meta_dtor_node{
             internal::meta_dtor_node{
                 +[](void *instance) { std::invoke(Func, *static_cast<Type *>(instance)); }});
                 +[](void *instance) { std::invoke(Func, *static_cast<Type *>(instance)); }});
 
 
@@ -326,11 +327,13 @@ public:
      */
      */
     template<auto Data, typename Policy = as_is_t>
     template<auto Data, typename Policy = as_is_t>
     auto data(const id_type id) noexcept {
     auto data(const id_type id) noexcept {
+        static_assert(std::is_base_of_v<meta_policy, Policy>, "Unknown policy type");
+
         if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
         if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
             using data_type = std::remove_reference_t<std::invoke_result_t<decltype(Data), Type &>>;
             using data_type = std::remove_reference_t<std::invoke_result_t<decltype(Data), Type &>>;
 
 
             auto &&elem = internal::meta_extend(
             auto &&elem = internal::meta_extend(
-                internal::owner(*info, *ctx),
+                internal::owner(*ctx, *info),
                 id,
                 id,
                 internal::meta_data_node{
                 internal::meta_data_node{
                     /* this is never static */
                     /* this is never static */
@@ -346,7 +349,7 @@ public:
             using data_type = std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>;
             using data_type = std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>;
 
 
             auto &&elem = internal::meta_extend(
             auto &&elem = internal::meta_extend(
-                internal::owner(*info, *ctx),
+                internal::owner(*ctx, *info),
                 id,
                 id,
                 internal::meta_data_node{
                 internal::meta_data_node{
                     ((std::is_same_v<Type, std::remove_const_t<data_type>> || std::is_const_v<data_type>) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static,
                     ((std::is_same_v<Type, std::remove_const_t<data_type>> || std::is_const_v<data_type>) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static,
@@ -385,11 +388,12 @@ public:
     template<auto Setter, auto Getter, typename Policy = as_is_t>
     template<auto Setter, auto Getter, typename Policy = as_is_t>
     auto data(const id_type id) noexcept {
     auto data(const id_type id) noexcept {
         using data_type = std::invoke_result_t<decltype(Getter), Type &>;
         using data_type = std::invoke_result_t<decltype(Getter), Type &>;
+        static_assert(std::is_base_of_v<meta_policy, Policy>, "Unknown policy type");
         static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
         static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
 
 
         if constexpr(std::is_same_v<decltype(Setter), std::nullptr_t>) {
         if constexpr(std::is_same_v<decltype(Setter), std::nullptr_t>) {
             auto &&elem = internal::meta_extend(
             auto &&elem = internal::meta_extend(
-                internal::owner(*info, *ctx),
+                internal::owner(*ctx, *info),
                 id,
                 id,
                 internal::meta_data_node{
                 internal::meta_data_node{
                     /* this is never static */
                     /* this is never static */
@@ -405,7 +409,7 @@ public:
             using args_type = typename meta_function_helper_t<Type, decltype(Setter)>::args_type;
             using args_type = typename meta_function_helper_t<Type, decltype(Setter)>::args_type;
 
 
             auto &&elem = internal::meta_extend(
             auto &&elem = internal::meta_extend(
-                internal::owner(*info, *ctx),
+                internal::owner(*ctx, *info),
                 id,
                 id,
                 internal::meta_data_node{
                 internal::meta_data_node{
                     /* this is never static nor const */
                     /* this is never static nor const */
@@ -441,6 +445,7 @@ public:
      */
      */
     template<typename Setter, auto Getter, typename Policy = as_is_t>
     template<typename Setter, auto Getter, typename Policy = as_is_t>
     auto data(const id_type id) noexcept {
     auto data(const id_type id) noexcept {
+        static_assert(std::is_base_of_v<meta_policy, Policy>, "Unknown policy type");
         data<Setter, Getter, Policy>(id, std::make_index_sequence<Setter::size>{});
         data<Setter, Getter, Policy>(id, std::make_index_sequence<Setter::size>{});
         return *this;
         return *this;
     }
     }
@@ -461,10 +466,11 @@ public:
     template<auto Candidate, typename Policy = as_is_t>
     template<auto Candidate, typename Policy = as_is_t>
     auto func(const id_type id) noexcept {
     auto func(const id_type id) noexcept {
         using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
         using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
+        static_assert(std::is_base_of_v<meta_policy, Policy>, "Unknown policy type");
         static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy");
         static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy");
 
 
         auto &&elem = internal::meta_extend(
         auto &&elem = internal::meta_extend(
-            internal::owner(*info, *ctx),
+            internal::owner(*ctx, *info),
             id,
             id,
             internal::meta_func_node{
             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),
                 (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.
  * @return A meta factory for the given type.
  */
  */
 template<typename Type>
 template<typename Type>
-[[nodiscard]] auto meta(meta_ctx &ctx = locator<meta_ctx>::value_or()) noexcept {
+[[nodiscard]] auto meta(meta_ctx &ctx) noexcept {
     auto &&context = internal::meta_context::from(ctx);
     auto &&context = internal::meta_context::from(ctx);
     // make sure the type exists in the context before returning a factory
     // make sure the type exists in the context before returning a factory
     context.value.try_emplace(type_id<Type>().hash(), internal::resolve<Type>(context));
     context.value.try_emplace(type_id<Type>().hash(), internal::resolve<Type>(context));
     return meta_factory<Type>{ctx};
     return meta_factory<Type>{ctx};
 }
 }
 
 
+/**
+ * @brief Utility function to use for reflection.
+ *
+ * This is the point from which everything starts.<br/>
+ * 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<typename Type>
+[[nodiscard]] auto meta() noexcept {
+    return meta<Type>(locator<meta_ctx>::value_or());
+}
+
 /**
 /**
  * @brief Resets a type and all its parts.
  * @brief Resets a type and all its parts.
  *
  *
@@ -547,7 +569,7 @@ template<typename Type>
  * @param id Unique identifier.
  * @param id Unique identifier.
  * @param ctx The context from which to reset meta types.
  * @param ctx The context from which to reset meta types.
  */
  */
-inline void meta_reset(const id_type id, meta_ctx &ctx = locator<meta_ctx>::value_or()) noexcept {
+inline void meta_reset(meta_ctx &ctx, const id_type id) noexcept {
     auto &&context = internal::meta_context::from(ctx);
     auto &&context = internal::meta_context::from(ctx);
 
 
     for(auto it = context.value.begin(); it != context.value.end();) {
     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<meta_ctx>::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.<br/>
+ * 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<meta_ctx>::value_or(), id);
+}
+
 /**
 /**
  * @brief Resets a type and all its parts.
  * @brief Resets a type and all its parts.
  *
  *
@@ -568,10 +605,22 @@ inline void meta_reset(const id_type id, meta_ctx &ctx = locator<meta_ctx>::valu
  * @param ctx The context from which to reset meta types.
  * @param ctx The context from which to reset meta types.
  */
  */
 template<typename Type>
 template<typename Type>
-void meta_reset(meta_ctx &ctx = locator<meta_ctx>::value_or()) noexcept {
+void meta_reset(meta_ctx &ctx) noexcept {
     internal::meta_context::from(ctx).value.erase(type_id<Type>().hash());
     internal::meta_context::from(ctx).value.erase(type_id<Type>().hash());
 }
 }
 
 
+/**
+ * @brief Resets a type and all its parts.
+ *
+ * @sa meta_reset
+ *
+ * @tparam Type Type to reset.
+ */
+template<typename Type>
+void meta_reset() noexcept {
+    meta_reset<Type>(locator<meta_ctx>::value_or());
+}
+
 /**
 /**
  * @brief Resets all meta types.
  * @brief Resets all meta types.
  *
  *
@@ -579,10 +628,19 @@ void meta_reset(meta_ctx &ctx = locator<meta_ctx>::value_or()) noexcept {
  *
  *
  * @param ctx The context from which to reset meta types.
  * @param ctx The context from which to reset meta types.
  */
  */
-inline void meta_reset(meta_ctx &ctx = locator<meta_ctx>::value_or()) noexcept {
+inline void meta_reset(meta_ctx &ctx) noexcept {
     internal::meta_context::from(ctx).value.clear();
     internal::meta_context::from(ctx).value.clear();
 }
 }
 
 
+/**
+ * @brief Resets all meta types.
+ *
+ * @sa meta_reset
+ */
+inline void meta_reset() noexcept {
+    meta_reset(locator<meta_ctx>::value_or());
+}
+
 } // namespace entt
 } // namespace entt
 
 
 #endif
 #endif

+ 73 - 58
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)},
         : storage{std::move(ref)},
           ctx{&area},
           ctx{&area},
           node{storage ? other.node : internal::meta_type_node{}},
           node{storage ? other.node : internal::meta_type_node{}},
           vtable{storage ? other.vtable : &basic_vtable<void>} {}
           vtable{storage ? other.vtable : &basic_vtable<void>} {}
 
 
 public:
 public:
+    /*! Default constructor. */
+    meta_any() noexcept
+        : meta_any{locator<meta_ctx>::value_or()} {}
+
     /**
     /**
      * @brief Context aware constructor.
      * @brief Context aware constructor.
      * @param area The context from which to search for meta types.
      * @param area The context from which to search for meta types.
      */
      */
-    meta_any(const meta_ctx &area = locator<meta_ctx>::value_or()) noexcept
+    meta_any(const meta_ctx &area) noexcept
         : storage{},
         : storage{},
           ctx{&area},
           ctx{&area},
           node{},
           node{},
@@ -222,7 +226,7 @@ public:
      * @tparam Type Type of object to use to initialize the wrapper.
      * @tparam Type Type of object to use to initialize the wrapper.
      * @param value An instance of an object to use to initialize the wrapper.
      * @param value An instance of an object to use to initialize the wrapper.
      */
      */
-    template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
+    template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any> && !std::is_same_v<std::decay_t<Type>, meta_ctx>>>
     meta_any(Type &&value)
     meta_any(Type &&value)
         : meta_any{std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
         : meta_any{std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
 
 
@@ -350,7 +354,7 @@ public:
     template<typename Type>
     template<typename Type>
     [[nodiscard]] const Type *try_cast() const {
     [[nodiscard]] const Type *try_cast() const {
         const auto other = internal::resolve<std::remove_cv_t<Type>>(internal::meta_context::from(*ctx));
         const auto other = internal::resolve<std::remove_cv_t<Type>>(internal::meta_context::from(*ctx));
-        return static_cast<const Type *>(internal::try_cast(node, other, data(), internal::meta_context::from(*ctx)));
+        return static_cast<const Type *>(internal::try_cast(internal::meta_context::from(*ctx), node, other, data()));
     }
     }
 
 
     /*! @copydoc try_cast */
     /*! @copydoc try_cast */
@@ -360,7 +364,7 @@ public:
             return std::as_const(*this).try_cast<std::remove_const_t<Type>>();
             return std::as_const(*this).try_cast<std::remove_const_t<Type>>();
         } else {
         } else {
             const auto other = internal::resolve<std::remove_cv_t<Type>>(internal::meta_context::from(*ctx));
             const auto other = internal::resolve<std::remove_cv_t<Type>>(internal::meta_context::from(*ctx));
-            return static_cast<Type *>(const_cast<void *>(internal::try_cast(node, other, data(), internal::meta_context::from(*ctx))));
+            return static_cast<Type *>(const_cast<void *>(internal::try_cast(internal::meta_context::from(*ctx), node, other, data())));
         }
         }
     }
     }
 
 
@@ -428,7 +432,7 @@ public:
             return {};
             return {};
         } else {
         } else {
             auto target = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
             auto target = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
-            return allow_cast({target, *ctx});
+            return allow_cast({*ctx, target});
         }
         }
     }
     }
 
 
@@ -442,9 +446,9 @@ public:
         auto target = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
         auto target = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
 
 
         if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
         if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
-            return allow_cast({target, *ctx}) && (storage.data() != nullptr);
+            return allow_cast({*ctx, target}) && (storage.data() != nullptr);
         } else {
         } else {
-            return allow_cast({target, *ctx});
+            return allow_cast({*ctx, target});
         }
         }
     }
     }
 
 
@@ -540,12 +544,12 @@ public:
 
 
     /*! @copydoc any::as_ref */
     /*! @copydoc any::as_ref */
     [[nodiscard]] meta_any as_ref() noexcept {
     [[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 */
     /*! @copydoc any::as_ref */
     [[nodiscard]] meta_any as_ref() const noexcept {
     [[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 */
     /*! @copydoc any::owner */
@@ -580,13 +584,24 @@ meta_any make_meta(Args &&...args) {
  * @return A properly initialized and not necessarily owning wrapper.
  * @return A properly initialized and not necessarily owning wrapper.
  */
  */
 template<typename Type>
 template<typename Type>
-meta_any forward_as_meta(Type &&value, const meta_ctx &ctx = locator<meta_ctx>::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
     // TODO it would be great if we had value and context construction support for meta_any
     meta_any elem{ctx};
     meta_any elem{ctx};
     elem.emplace<Type &&>(std::forward<Type>(value));
     elem.emplace<Type &&>(std::forward<Type>(value));
     return elem;
     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<typename Type>
+meta_any forward_as_meta(Type &&value) {
+    return forward_as_meta(locator<meta_ctx>::value_or(), std::forward<Type>(value));
+}
+
 /**
 /**
  * @brief Opaque pointers to instances of any type.
  * @brief Opaque pointers to instances of any type.
  *
  *
@@ -666,10 +681,10 @@ struct meta_prop {
 
 
     /**
     /**
      * @brief Context aware constructor for meta objects.
      * @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 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},
         : node{&curr},
           ctx{&area} {}
           ctx{&area} {}
 
 
@@ -678,7 +693,7 @@ struct meta_prop {
      * @return A wrapper containing the value stored with the property.
      * @return A wrapper containing the value stored with the property.
      */
      */
     [[nodiscard]] meta_any value() const {
     [[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.
      * @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 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},
         : node{&curr},
           ctx{&area} {}
           ctx{&area} {}
 
 
@@ -755,7 +770,7 @@ struct meta_data {
      */
      */
     template<typename Type>
     template<typename Type>
     bool set(meta_handle instance, Type &&value) const {
     bool set(meta_handle instance, Type &&value) const {
-        return node->set && node->set(std::move(instance), std::forward<Type>(value), *ctx);
+        return node->set && node->set(*ctx, std::move(instance), std::forward<Type>(value));
     }
     }
 
 
     /**
     /**
@@ -768,7 +783,7 @@ struct meta_data {
      * @return A wrapper containing the value of the underlying variable.
      * @return A wrapper containing the value of the underlying variable.
      */
      */
     [[nodiscard]] meta_any get(meta_handle instance) const {
     [[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.
      * @return An iterable range to visit registered meta properties.
      */
      */
     [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_data_node::prop)::const_iterator> prop() const noexcept {
     [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_data_node::prop)::const_iterator> 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 {
     [[nodiscard]] meta_prop prop(const id_type key) const {
         const auto it = node->prop.find(key);
         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.
      * @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 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},
         : node{&curr},
           ctx{&area} {}
           ctx{&area} {}
 
 
@@ -880,7 +895,7 @@ struct meta_func {
      * @return A wrapper containing the returned value, if any.
      * @return A wrapper containing the returned value, if any.
      */
      */
     meta_any invoke(meta_handle instance, meta_any *const args, const size_type sz) const {
     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 */
     /*! @copydoc meta_data::prop */
     [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_func_node::prop)::const_iterator> prop() const noexcept {
     [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_func_node::prop)::const_iterator> 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 {
     [[nodiscard]] meta_prop prop(const id_type key) const {
         const auto it = node->prop.find(key);
         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.
      * @return The next overload of the given function, if any.
      */
      */
     [[nodiscard]] meta_func next() const {
     [[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{};
                 size_type pos{};
 
 
                 for(; pos < sz && args[pos]; ++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();
                     const auto type = args[pos].type();
 
 
                     if(const auto &info = other.info(); info == type.info()) {
                     if(const auto &info = other.info(); info == type.info()) {
@@ -1011,20 +1026,20 @@ public:
 
 
     /**
     /**
      * @brief Context aware constructor for meta objects.
      * @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 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},
         : node{curr},
           ctx{&area} {}
           ctx{&area} {}
 
 
     /**
     /**
      * @brief Context aware constructor for meta objects.
      * @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 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.
      * @brief Returns the type info object of the underlying type.
@@ -1113,7 +1128,7 @@ public:
      * doesn't refer to a pointer type.
      * doesn't refer to a pointer type.
      */
      */
     [[nodiscard]] meta_type remove_pointer() const noexcept {
     [[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.
      * @return The tag for the class template of the underlying type.
      */
      */
     [[nodiscard]] inline meta_type template_type() const noexcept {
     [[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.
      * @return The type of the i-th template argument of a type.
      */
      */
     [[nodiscard]] inline meta_type template_arg(const size_type index) const noexcept {
     [[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<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator> base() const noexcept {
     [[nodiscard]] meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator> base() const noexcept {
         using range_type = meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator>;
         using range_type = meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator>;
-        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<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator> data() const noexcept {
     [[nodiscard]] meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator> data() const noexcept {
         using range_type = meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator>;
         using range_type = meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator>;
-        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 {
     [[nodiscard]] meta_data data(const id_type id) const {
         if(node.details) {
         if(node.details) {
             if(const auto it = node.details->data.find(id); it != node.details->data.cend()) {
             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<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator> func() const noexcept {
     [[nodiscard]] meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator> func() const noexcept {
         using return_type = meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator>;
         using return_type = meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator>;
-        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 {
     [[nodiscard]] meta_func func(const id_type id) const {
         if(node.details) {
         if(node.details) {
             if(const auto it = node.details->func.find(id); it != node.details->func.cend()) {
             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) {
             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.
      * @return A wrapper that references the given instance.
      */
      */
     meta_any from_void(void *element) const {
     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 */
     /*! @copydoc from_void */
     meta_any from_void(const void *element) const {
     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) {
                 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<meta_prop, typename decltype(internal::meta_type_descriptor::prop)::const_iterator> prop() const noexcept {
     [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_type_descriptor::prop)::const_iterator> prop() const noexcept {
         using range_type = meta_range<meta_prop, typename decltype(internal::meta_type_descriptor::prop)::const_iterator>;
         using range_type = meta_range<meta_prop, typename decltype(internal::meta_type_descriptor::prop)::const_iterator>;
-        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 {
     [[nodiscard]] meta_prop prop(const id_type key) const {
         if(node.details) {
         if(node.details) {
             if(const auto it = node.details->prop.find(key); it != node.details->prop.cend()) {
             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 {
 [[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<typename... Args>
 template<typename... Args>
@@ -1477,7 +1492,7 @@ bool meta_any::set(const id_type id, Type &&value) {
 
 
     if(const auto *value = data(); node.details) {
     if(const auto *value = data(); node.details) {
         for(auto &&curr: node.details->base) {
         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) {
             if(auto other = as_const.allow_cast(type); other) {
                 return 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()) {
         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) {
 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));
     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 {
 [[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 {
 [[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 {
 [[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 {
 [[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 {
 [[nodiscard]] inline meta_type meta_sequence_container::value_type() const noexcept {
     auto &&ctx_TODO = locator<meta_ctx>::value_or();
     auto &&ctx_TODO = locator<meta_ctx>::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 {
 [[nodiscard]] inline meta_type meta_associative_container::key_type() const noexcept {
     auto &&ctx_TODO = locator<meta_ctx>::value_or();
     auto &&ctx_TODO = locator<meta_ctx>::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 {
 [[nodiscard]] inline meta_type meta_associative_container::mapped_type() const noexcept {
     auto &&ctx_TODO = locator<meta_ctx>::value_or();
     auto &&ctx_TODO = locator<meta_ctx>::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 */
 /*! @copydoc meta_sequence_container::value_type */
 [[nodiscard]] inline meta_type meta_associative_container::value_type() const noexcept {
 [[nodiscard]] inline meta_type meta_associative_container::value_type() const noexcept {
     auto &&ctx_TODO = locator<meta_ctx>::value_or();
     auto &&ctx_TODO = locator<meta_ctx>::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 */
 /*! @copydoc meta_sequence_container::size */

+ 17 - 17
src/entt/meta/node.hpp

@@ -59,15 +59,15 @@ struct meta_base_node {
 };
 };
 
 
 struct meta_conv_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 {
 struct meta_ctor_node {
     using size_type = std::size_t;
     using size_type = std::size_t;
 
 
     size_type arity{0u};
     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 {
 struct meta_dtor_node {
@@ -80,9 +80,9 @@ struct meta_data_node {
     meta_traits traits{meta_traits::is_none};
     meta_traits traits{meta_traits::is_none};
     size_type arity{0u};
     size_type arity{0u};
     meta_type_node (*type)(const meta_context &) noexcept {};
     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<id_type, meta_prop_node, identity> prop{};
     dense_map<id_type, meta_prop_node, identity> prop{};
 };
 };
 
 
@@ -92,8 +92,8 @@ struct meta_func_node {
     meta_traits traits{meta_traits::is_none};
     meta_traits traits{meta_traits::is_none};
     size_type arity{0u};
     size_type arity{0u};
     meta_type_node (*ret)(const meta_context &) noexcept {};
     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<meta_func_node> next{};
     std::shared_ptr<meta_func_node> next{};
     dense_map<id_type, meta_prop_node, identity> prop{};
     dense_map<id_type, meta_prop_node, identity> prop{};
 };
 };
@@ -103,7 +103,7 @@ struct meta_template_node {
 
 
     size_type arity{0u};
     size_type arity{0u};
     meta_type_node (*type)(const meta_context &) noexcept {};
     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 {
 struct meta_type_descriptor {
@@ -125,7 +125,7 @@ struct meta_type_node {
     meta_type_node (*remove_pointer)(const meta_context &) noexcept {};
     meta_type_node (*remove_pointer)(const meta_context &) noexcept {};
     meta_any (*default_constructor)(const meta_ctx &){};
     meta_any (*default_constructor)(const meta_ctx &){};
     double (*conversion_helper)(void *, const void *){};
     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_template_node templ{};
     meta_dtor_node dtor{};
     meta_dtor_node dtor{};
     std::shared_ptr<meta_type_descriptor> details{};
     std::shared_ptr<meta_type_descriptor> details{};
@@ -140,7 +140,7 @@ template<typename Type>
 }
 }
 
 
 template<typename... Args>
 template<typename... Args>
-[[nodiscard]] auto meta_arg_node(type_list<Args...>, [[maybe_unused]] const std::size_t index, const meta_context &context) noexcept {
+[[nodiscard]] auto meta_arg_node(const meta_context &context, type_list<Args...>, [[maybe_unused]] const std::size_t index) noexcept {
     std::size_t pos{};
     std::size_t pos{};
     meta_type_node (*value)(const meta_context &) noexcept = nullptr;
     meta_type_node (*value)(const meta_context &) noexcept = nullptr;
     ((value = (pos++ == index ? &resolve<std::remove_cv_t<std::remove_reference_t<Args>>> : value)), ...);
     ((value = (pos++ == index ? &resolve<std::remove_cv_t<std::remove_reference_t<Args>>> : value)), ...);
@@ -148,14 +148,14 @@ template<typename... Args>
     return value(context);
     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) {
     if(from.info && to.info && *from.info == *to.info) {
         return instance;
         return instance;
     }
     }
 
 
     if(from.details) {
     if(from.details) {
         for(auto &&curr: from.details->base) {
         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;
                 return elem;
             }
             }
         }
         }
@@ -164,7 +164,7 @@ template<typename... Args>
     return nullptr;
     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());
     const auto it = context.value.find(info.hash());
     return it != context.value.end() ? &it->second : nullptr;
     return it != context.value.end() ? &it->second : nullptr;
 }
 }
@@ -197,7 +197,7 @@ void meta_conversion_helper([[maybe_unused]] meta_type_node &node) {
 template<typename Type>
 template<typename Type>
 void meta_from_void([[maybe_unused]] meta_type_node &node) {
 void meta_from_void([[maybe_unused]] meta_type_node &node) {
     if constexpr(!std::is_same_v<Type, void> && !std::is_function_v<Type>) {
     if constexpr(!std::is_same_v<Type, void> && !std::is_function_v<Type>) {
-        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
             // TODO it would be great if we had value and context construction support for meta_any
             meta_any elem{ctx};
             meta_any elem{ctx};
             element ? elem.emplace<std::decay_t<Type> &>(*static_cast<std::decay_t<Type> *>(element)) : elem.emplace<const std::decay_t<Type> &>(*static_cast<const std::decay_t<Type> *>(as_const));
             element ? elem.emplace<std::decay_t<Type> &>(*static_cast<std::decay_t<Type> *>(element)) : elem.emplace<const std::decay_t<Type> &>(*static_cast<const std::decay_t<Type> *>(as_const));
@@ -210,7 +210,7 @@ template<typename Type>
 [[nodiscard]] meta_type_node resolve(const meta_context &context) noexcept {
 [[nodiscard]] meta_type_node resolve(const meta_context &context) noexcept {
     static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");
     static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type");
 
 
-    if(auto *elem = try_resolve(type_id<Type>(), context); elem) {
+    if(auto *elem = try_resolve(context, type_id<Type>()); elem) {
         return *elem;
         return *elem;
     }
     }
 
 
@@ -237,7 +237,7 @@ template<typename Type>
         node.templ = meta_template_node{
         node.templ = meta_template_node{
             meta_template_traits<Type>::args_type::size,
             meta_template_traits<Type>::args_type::size,
             &resolve<typename meta_template_traits<Type>::class_type>,
             &resolve<typename meta_template_traits<Type>::class_type>,
-            +[](const std::size_t index, const meta_context &area) noexcept { return meta_arg_node(typename meta_template_traits<Type>::args_type{}, index, area); }};
+            +[](const meta_context &area, const std::size_t index) noexcept { return meta_arg_node(area, typename meta_template_traits<Type>::args_type{}, index); }};
     }
     }
 
 
     return node;
     return node;

+ 7 - 4
src/entt/meta/policy.hpp

@@ -5,8 +5,11 @@
 
 
 namespace entt {
 namespace entt {
 
 
+/*! @brief Basic common class for meta policies. */
+struct meta_policy {};
+
 /*! @brief Empty class type used to request the _as ref_ 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
      * @cond TURN_OFF_DOXYGEN
      * Internal details not to be documented.
      * 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. */
 /*! @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
      * @cond TURN_OFF_DOXYGEN
      * Internal details not to be documented.
      * 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. */
 /*! @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
      * @cond TURN_OFF_DOXYGEN
      * Internal details not to be documented.
      * 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. */
 /*! @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
      * @cond TURN_OFF_DOXYGEN
      * Internal details not to be documented.
      * Internal details not to be documented.

+ 3 - 3
src/entt/meta/range.hpp

@@ -29,7 +29,7 @@ struct meta_range_iterator final {
         : it{},
         : it{},
           ctx{} {}
           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},
         : it{iter},
           ctx{&area} {}
           ctx{&area} {}
 
 
@@ -70,7 +70,7 @@ struct meta_range_iterator final {
     }
     }
 
 
     [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept {
     [[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 {
     [[nodiscard]] constexpr pointer operator->() const noexcept {
@@ -78,7 +78,7 @@ struct meta_range_iterator final {
     }
     }
 
 
     [[nodiscard]] constexpr reference operator*() const noexcept {
     [[nodiscard]] constexpr reference operator*() const noexcept {
-        return {it->first, Type{it->second, *ctx}};
+        return {it->first, Type{*ctx, it->second}};
     }
     }
 
 
     template<typename... Args>
     template<typename... Args>

+ 46 - 10
src/entt/meta/resolve.hpp

@@ -18,9 +18,19 @@ namespace entt {
  * @return The meta type associated with the given type, if any.
  * @return The meta type associated with the given type, if any.
  */
  */
 template<typename Type>
 template<typename Type>
-[[nodiscard]] meta_type resolve(const meta_ctx &ctx = locator<meta_ctx>::value_or()) noexcept {
+[[nodiscard]] meta_type resolve(const meta_ctx &ctx) noexcept {
     auto &&context = internal::meta_context::from(ctx);
     auto &&context = internal::meta_context::from(ctx);
-    return {internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(context), ctx};
+    return {ctx, internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(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<typename Type>
+[[nodiscard]] meta_type resolve() noexcept {
+    return resolve<Type>(locator<meta_ctx>::value_or());
 }
 }
 
 
 /**
 /**
@@ -28,18 +38,26 @@ template<typename Type>
  * @param ctx The context from which to search for meta types.
  * @param ctx The context from which to search for meta types.
  * @return An iterable range to use to visit all meta types.
  * @return An iterable range to use to visit all meta types.
  */
  */
-[[nodiscard]] inline meta_range<meta_type, typename decltype(internal::meta_context::value)::const_iterator> resolve(const meta_ctx &ctx = locator<meta_ctx>::value_or()) noexcept {
+[[nodiscard]] inline meta_range<meta_type, typename decltype(internal::meta_context::value)::const_iterator> resolve(const meta_ctx &ctx) noexcept {
     auto &&context = internal::meta_context::from(ctx);
     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<meta_type, typename decltype(internal::meta_context::value)::const_iterator> resolve() noexcept {
+    return resolve(locator<meta_ctx>::value_or());
 }
 }
 
 
 /**
 /**
  * @brief Returns the meta type associated with a given identifier, if any.
  * @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 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.
  * @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<meta_ctx>::value_or()) noexcept {
+[[nodiscard]] inline meta_type resolve(const meta_ctx &ctx, const id_type id) noexcept {
     for(auto &&curr: resolve(ctx)) {
     for(auto &&curr: resolve(ctx)) {
         if(curr.second.id() == id) {
         if(curr.second.id() == id) {
             return curr.second;
             return curr.second;
@@ -49,16 +67,34 @@ template<typename Type>
     return {};
     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<meta_ctx>::value_or(), id);
+}
+
 /**
 /**
  * @brief Returns the meta type associated with a given type info object.
  * @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 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.
  * @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<meta_ctx>::value_or()) noexcept {
+[[nodiscard]] inline meta_type resolve(const meta_ctx &ctx, const type_info &info) noexcept {
     auto &&context = internal::meta_context::from(ctx);
     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<meta_ctx>::value_or(), info);
 }
 }
 
 
 } // namespace entt
 } // namespace entt

+ 124 - 19
src/entt/meta/utility.hpp

@@ -156,7 +156,7 @@ using meta_function_helper_t = typename meta_function_helper<Type, Candidate>::t
  * @return A meta any containing the returned value, if any.
  * @return A meta any containing the returned value, if any.
  */
  */
 template<typename Policy = as_is_t, typename Type>
 template<typename Policy = as_is_t, typename Type>
-meta_any meta_dispatch([[maybe_unused]] Type &&value) {
+std::enable_if_t<std::is_base_of_v<meta_policy, Policy>, meta_any> meta_dispatch([[maybe_unused]] Type &&value) {
     if constexpr(std::is_same_v<Policy, as_void_t>) {
     if constexpr(std::is_same_v<Policy, as_void_t>) {
         return meta_any{std::in_place_type<void>};
         return meta_any{std::in_place_type<void>};
     } else if constexpr(std::is_same_v<Policy, as_ref_t>) {
     } else if constexpr(std::is_same_v<Policy, as_ref_t>) {
@@ -165,7 +165,6 @@ meta_any meta_dispatch([[maybe_unused]] Type &&value) {
         static_assert(std::is_lvalue_reference_v<Type>, "Invalid type");
         static_assert(std::is_lvalue_reference_v<Type>, "Invalid type");
         return meta_any{std::in_place_type<const std::remove_reference_t<Type> &>, std::as_const(value)};
         return meta_any{std::in_place_type<const std::remove_reference_t<Type> &>, std::as_const(value)};
     } else {
     } else {
-        static_assert(std::is_same_v<Policy, as_is_t>, "Policy not supported");
         return meta_any{std::forward<Type>(value)};
         return meta_any{std::forward<Type>(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.
  * @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.
  * @tparam Type Type list of the actual types of arguments.
  * @param ctx The context from which to search for meta types.
  * @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.
  * @return The meta type of the i-th element of the list of arguments.
  */
  */
 template<typename Type>
 template<typename Type>
-[[nodiscard]] static meta_type meta_arg(const std::size_t index, const meta_ctx &ctx = locator<meta_ctx>::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);
     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<typename Type>
+[[nodiscard]] static meta_type meta_arg(const std::size_t index) noexcept {
+    return meta_arg<Type>(locator<meta_ctx>::value_or(), index);
 }
 }
 
 
 /**
 /**
  * @brief Sets the value of a given variable.
  * @brief Sets the value of a given variable.
  * @tparam Type Reflected type to which the variable is associated.
  * @tparam Type Reflected type to which the variable is associated.
  * @tparam Data The actual variable to set.
  * @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 instance An opaque instance of the underlying type, if required.
  * @param value Parameter to use to set the variable.
  * @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.
  * @return True in case of success, false otherwise.
  */
  */
 template<typename Type, auto Data>
 template<typename Type, auto Data>
-[[nodiscard]] bool meta_setter([[maybe_unused]] meta_handle instance, [[maybe_unused]] meta_any value, const meta_ctx &ctx /*_TODO*/ = locator<meta_ctx>::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<decltype(Data), Type> && !std::is_same_v<decltype(Data), std::nullptr_t>) {
     if constexpr(!std::is_same_v<decltype(Data), Type> && !std::is_same_v<decltype(Data), std::nullptr_t>) {
         if constexpr(std::is_member_function_pointer_v<decltype(Data)> || std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) {
         if constexpr(std::is_member_function_pointer_v<decltype(Data)> || std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) {
             using descriptor = meta_function_helper_t<Type, decltype(Data)>;
             using descriptor = meta_function_helper_t<Type, decltype(Data)>;
@@ -226,17 +237,30 @@ template<typename Type, auto Data>
     return false;
     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<typename Type, auto Data>
+[[nodiscard]] bool meta_setter([[maybe_unused]] meta_handle instance, [[maybe_unused]] meta_any value) {
+    return meta_setter<Type, Data>(locator<meta_ctx>::value_or(), std::move(instance), std::move(value));
+}
+
 /**
 /**
  * @brief Gets the value of a given variable.
  * @brief Gets the value of a given variable.
  * @tparam Type Reflected type to which the variable is associated.
  * @tparam Type Reflected type to which the variable is associated.
  * @tparam Data The actual variable to get.
  * @tparam Data The actual variable to get.
  * @tparam Policy Optional policy (no policy set by default).
  * @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 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.
  * @return A meta any containing the value of the underlying variable.
  */
  */
 template<typename Type, auto Data, typename Policy = as_is_t>
 template<typename Type, auto Data, typename Policy = as_is_t>
-[[nodiscard]] meta_any meta_getter([[maybe_unused]] meta_handle instance, const meta_ctx &ctx /*_TODO*/ = locator<meta_ctx>::value_or()) {
+[[nodiscard]] std::enable_if_t<std::is_base_of_v<meta_policy, Policy>, meta_any> meta_getter(const meta_ctx &ctx /*_TODO*/, [[maybe_unused]] meta_handle instance) {
     if constexpr(std::is_member_pointer_v<decltype(Data)> || std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) {
     if constexpr(std::is_member_pointer_v<decltype(Data)> || std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) {
         if constexpr(!std::is_array_v<std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<decltype(Data), Type &>>>>) {
         if constexpr(!std::is_array_v<std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<decltype(Data), Type &>>>>) {
             if constexpr(std::is_invocable_v<decltype(Data), Type &>) {
             if constexpr(std::is_invocable_v<decltype(Data), Type &>) {
@@ -264,6 +288,19 @@ template<typename Type, auto Data, typename Policy = as_is_t>
     }
     }
 }
 }
 
 
+/**
+ * @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<typename Type, auto Data, typename Policy = as_is_t>
+[[nodiscard]] std::enable_if_t<std::is_base_of_v<meta_policy, Policy>, meta_any> meta_getter([[maybe_unused]] meta_handle instance) {
+    return meta_getter<Type, Data, Policy>(locator<meta_ctx>::value_or(), std::move(instance));
+}
+
 /**
 /**
  * @cond TURN_OFF_DOXYGEN
  * @cond TURN_OFF_DOXYGEN
  * Internal details not to be documented.
  * Internal details not to be documented.
@@ -323,57 +360,98 @@ template<typename Type, typename... Args, std::size_t... Index>
  * @tparam Type Reflected type to which the object to _invoke_ is associated.
  * @tparam Type Reflected type to which the object to _invoke_ is associated.
  * @tparam Policy Optional policy (no policy set by default).
  * @tparam Policy Optional policy (no policy set by default).
  * @tparam Candidate The type of the actual object to _invoke_.
  * @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 instance An opaque instance of the underlying type, if required.
  * @param candidate The actual object to _invoke_.
  * @param candidate The actual object to _invoke_.
  * @param args Parameters to use to _invoke_ the object.
  * @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.
  * @return A meta any containing the returned value, if any.
  */
  */
 template<typename Type, typename Policy = as_is_t, typename Candidate>
 template<typename Type, typename Policy = as_is_t, typename Candidate>
-[[nodiscard]] meta_any meta_invoke(meta_handle instance, Candidate &&candidate, meta_any *const args, const meta_ctx &ctx /*_TODO*/ = locator<meta_ctx>::value_or()) {
+[[nodiscard]] std::enable_if_t<std::is_base_of_v<meta_policy, Policy>, meta_any> meta_invoke(const meta_ctx &ctx, meta_handle instance, Candidate &&candidate, meta_any *const args) {
     return internal::meta_invoke<Type, Policy>(std::move(instance), std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
     return internal::meta_invoke<Type, Policy>(std::move(instance), std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::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<typename Type, typename Policy = as_is_t, typename Candidate>
+[[nodiscard]] std::enable_if_t<std::is_base_of_v<meta_policy, Policy>, meta_any> meta_invoke(meta_handle instance, Candidate &&candidate, meta_any *const args) {
+    return meta_invoke<Type, Policy>(locator<meta_ctx>::value_or(), std::move(instance), std::forward<Candidate>(candidate), args);
+}
+
 /**
 /**
  * @brief Tries to invoke a function given a list of erased parameters.
  * @brief Tries to invoke a function given a list of erased parameters.
  * @tparam Type Reflected type to which the function is associated.
  * @tparam Type Reflected type to which the function is associated.
  * @tparam Candidate The actual function to invoke.
  * @tparam Candidate The actual function to invoke.
  * @tparam Policy Optional policy (no policy set by default).
  * @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 instance An opaque instance of the underlying type, if required.
  * @param args Parameters to use to invoke the function.
  * @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.
  * @return A meta any containing the returned value, if any.
  */
  */
 template<typename Type, auto Candidate, typename Policy = as_is_t>
 template<typename Type, auto Candidate, typename Policy = as_is_t>
-[[nodiscard]] meta_any meta_invoke(meta_handle instance, meta_any *const args, const meta_ctx &ctx /*_TODO*/ = locator<meta_ctx>::value_or()) {
+[[nodiscard]] std::enable_if_t<std::is_base_of_v<meta_policy, Policy>, meta_any> meta_invoke(const meta_ctx &ctx /*_TODO*/, meta_handle instance, meta_any *const args) {
     return internal::meta_invoke<Type, Policy>(std::move(instance), Candidate, args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<decltype(Candidate)>>::args_type::size>{});
     return internal::meta_invoke<Type, Policy>(std::move(instance), Candidate, args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<decltype(Candidate)>>::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.
+ * @tparam Candidate The actual function to invoke.
+ * @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.
+ * @return A meta any containing the returned value, if any.
+ */
+template<typename Type, auto Candidate, typename Policy = as_is_t>
+[[nodiscard]] std::enable_if_t<std::is_base_of_v<meta_policy, Policy>, meta_any> meta_invoke(meta_handle instance, meta_any *const args) {
+    return meta_invoke<Type, Candidate, Policy>(locator<meta_ctx>::value_or(), std::move(instance), args);
+}
+
 /**
 /**
  * @brief Tries to construct an instance given a list of erased parameters.
  * @brief Tries to construct an instance given a list of erased parameters.
  * @tparam Type Actual type of the instance to construct.
  * @tparam Type Actual type of the instance to construct.
  * @tparam Args Types of arguments expected.
  * @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.
  * @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.
  * @return A meta any containing the new instance, if any.
  */
  */
 template<typename Type, typename... Args>
 template<typename Type, typename... Args>
-[[nodiscard]] meta_any meta_construct(meta_any *const args, const meta_ctx &ctx /*_TODO*/ = locator<meta_ctx>::value_or()) {
+[[nodiscard]] meta_any meta_construct(const meta_ctx &ctx /*_TODO*/, meta_any *const args) {
     return internal::meta_construct<Type, Args...>(args, std::index_sequence_for<Args...>{});
     return internal::meta_construct<Type, Args...>(args, std::index_sequence_for<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 args Parameters to use to construct the instance.
+ * @return A meta any containing the new instance, if any.
+ */
+template<typename Type, typename... Args>
+[[nodiscard]] meta_any meta_construct(meta_any *const args) {
+    return meta_construct<Type, Args...>(locator<meta_ctx>::value_or(), args);
+}
+
 /**
 /**
  * @brief Tries to construct an instance given a list of erased parameters.
  * @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 Type Reflected type to which the object to _invoke_ is associated.
  * @tparam Policy Optional policy (no policy set by default).
  * @tparam Policy Optional policy (no policy set by default).
  * @tparam Candidate The type of the actual object to _invoke_.
  * @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 candidate The actual object to _invoke_.
  * @param args Parameters to use to _invoke_ the object.
  * @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.
  * @return A meta any containing the returned value, if any.
  */
  */
 template<typename Type, typename Policy = as_is_t, typename Candidate>
 template<typename Type, typename Policy = as_is_t, typename Candidate>
-[[nodiscard]] meta_any meta_construct(Candidate &&candidate, meta_any *const args, const meta_ctx &ctx /*_TODO*/ = locator<meta_ctx>::value_or()) {
+[[nodiscard]] std::enable_if_t<std::is_base_of_v<meta_policy, Policy>, meta_any> meta_construct(const meta_ctx &ctx /*_TODO*/, Candidate &&candidate, meta_any *const args) {
     if constexpr(meta_function_helper_t<Type, Candidate>::is_static || std::is_class_v<std::remove_cv_t<std::remove_reference_t<Candidate>>>) {
     if constexpr(meta_function_helper_t<Type, Candidate>::is_static || std::is_class_v<std::remove_cv_t<std::remove_reference_t<Candidate>>>) {
         return internal::meta_invoke<Type, Policy>({}, std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
         return internal::meta_invoke<Type, Policy>({}, std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
     } else {
     } else {
@@ -381,18 +459,45 @@ template<typename Type, typename Policy = as_is_t, typename Candidate>
     }
     }
 }
 }
 
 
+/**
+ * @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<typename Type, typename Policy = as_is_t, typename Candidate>
+[[nodiscard]] std::enable_if_t<std::is_base_of_v<meta_policy, Policy>, meta_any> meta_construct(Candidate &&candidate, meta_any *const args) {
+    return meta_construct<Type, Policy>(locator<meta_ctx>::value_or(), std::forward<Candidate>(candidate), args);
+}
+
 /**
 /**
  * @brief Tries to construct an instance given a list of erased parameters.
  * @brief Tries to construct an instance given a list of erased parameters.
  * @tparam Type Reflected type to which the function is associated.
  * @tparam Type Reflected type to which the function is associated.
  * @tparam Candidate The actual function to invoke.
  * @tparam Candidate The actual function to invoke.
  * @tparam Policy Optional policy (no policy set by default).
  * @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.
  * @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<typename Type, auto Candidate, typename Policy = as_is_t>
+[[nodiscard]] std::enable_if_t<std::is_base_of_v<meta_policy, Policy>, meta_any> meta_construct(const meta_ctx &ctx /*_TODO*/, meta_any *const args) {
+    return meta_construct<Type, Policy>(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.
  * @return A meta any containing the returned value, if any.
  * @return A meta any containing the returned value, if any.
  */
  */
 template<typename Type, auto Candidate, typename Policy = as_is_t>
 template<typename Type, auto Candidate, typename Policy = as_is_t>
-[[nodiscard]] meta_any meta_construct(meta_any *const args, const meta_ctx &ctx /*_TODO*/ = locator<meta_ctx>::value_or()) {
-    return meta_construct<Type, Policy>(Candidate, args);
+[[nodiscard]] std::enable_if_t<std::is_base_of_v<meta_policy, Policy>, meta_any> meta_construct(meta_any *const args) {
+    return meta_construct<Type, Candidate, Policy>(locator<meta_ctx>::value_or(), args);
 }
 }
 
 
 } // namespace entt
 } // namespace entt