meta: revert automatic policy (too convenient a feature)

This commit is contained in:
skypjack
2025-09-24 12:30:14 +02:00
parent 05863c6a15
commit 6ecf1f35c0
10 changed files with 174 additions and 98 deletions

View File

@@ -169,6 +169,7 @@ if(ENTT_INCLUDE_HEADERS)
meta/meta.hpp
meta/node.hpp
meta/pointer.hpp
meta/policy.hpp
meta/range.hpp
meta/resolve.hpp
meta/template.hpp

View File

@@ -50,6 +50,7 @@ namespace entt {}
#include "meta/meta.hpp"
#include "meta/node.hpp"
#include "meta/pointer.hpp"
#include "meta/policy.hpp"
#include "meta/range.hpp"
#include "meta/resolve.hpp"
#include "meta/template.hpp"

View File

@@ -19,6 +19,7 @@
#include "fwd.hpp"
#include "meta.hpp"
#include "node.hpp"
#include "policy.hpp"
#include "range.hpp"
#include "resolve.hpp"
#include "utility.hpp"
@@ -251,13 +252,15 @@ public:
* type is a built-in one or not.
*
* @tparam Candidate The actual function to use as a constructor.
* @tparam Policy Optional policy (no policy set by default).
* @return A meta factory for the parent type.
*/
template<auto Candidate>
template<auto Candidate, typename Policy = as_is_t>
meta_factory ctor() noexcept {
using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
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");
base_type::insert_or_assign(internal::meta_ctor_node{type_id<typename descriptor::args_type>().hash(), descriptor::args_type::size, &meta_arg<typename descriptor::args_type>, &meta_construct<Type, Candidate>});
base_type::insert_or_assign(internal::meta_ctor_node{type_id<typename descriptor::args_type>().hash(), descriptor::args_type::size, &meta_arg<typename descriptor::args_type>, &meta_construct<Type, Candidate, Policy>});
return *this;
}
@@ -285,12 +288,13 @@ public:
/**
* @brief Assigns a meta data to a meta type.
* @tparam Data The actual variable to attach to the meta type.
* @tparam Policy Optional policy (no policy set by default).
* @param name A custom unique identifier as a **string literal**.
* @return A meta factory for the given type.
*/
template<auto Data>
template<auto Data, typename Policy = as_is_t>
meta_factory data(const char *name) noexcept {
return data<Data>(entt::hashed_string::value(name), name);
return data<Data, Policy>(entt::hashed_string::value(name), name);
}
/**
@@ -302,14 +306,16 @@ public:
* reflected object will appear as if they were part of the type itself.
*
* @tparam Data The actual variable to attach to the meta type.
* @tparam Policy Optional policy (no policy set by default).
* @param id Unique identifier.
* @param name An optional name for the meta data as a **string literal**.
* @return A meta factory for the parent type.
*/
template<auto Data>
template<auto Data, typename Policy = as_is_t>
meta_factory data(const id_type id, const char *name = nullptr) noexcept {
if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
using data_type = std::invoke_result_t<decltype(Data), Type &>;
static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
base_type::data(
internal::meta_data_node{
@@ -321,10 +327,16 @@ public:
&internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>,
&meta_arg<type_list<std::remove_cv_t<std::remove_reference_t<data_type>>>>,
&meta_setter<Type, Data>,
&meta_getter<Type, Data>});
&meta_getter<Type, Data, Policy>});
} else {
using data_type = std::remove_pointer_t<decltype(Data)>;
if constexpr(std::is_pointer_v<decltype(Data)>) {
static_assert(Policy::template value<decltype(*Data)>, "Invalid return type for the given policy");
} else {
static_assert(Policy::template value<data_type>, "Invalid return type for the given policy");
}
base_type::data(
internal::meta_data_node{
id,
@@ -334,7 +346,7 @@ public:
&internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>,
&meta_arg<type_list<std::remove_cv_t<std::remove_reference_t<data_type>>>>,
&meta_setter<Type, Data>,
&meta_getter<Type, Data>});
&meta_getter<Type, Data, Policy>});
}
return *this;
@@ -345,12 +357,13 @@ public:
* getter.
* @tparam Setter The actual function to use as a setter.
* @tparam Getter The actual function to use as a getter.
* @tparam Policy Optional policy (no policy set by default).
* @param name A custom unique identifier as a **string literal**.
* @return A meta factory for the given type.
*/
template<auto Setter, auto Getter>
template<auto Setter, auto Getter, typename Policy = as_is_t>
meta_factory data(const char *name) noexcept {
return data<Setter, Getter>(entt::hashed_string::value(name), name);
return data<Setter, Getter, Policy>(entt::hashed_string::value(name), name);
}
/**
@@ -369,13 +382,15 @@ public:
*
* @tparam Setter The actual function to use as a setter.
* @tparam Getter The actual function to use as a getter.
* @tparam Policy Optional policy (no policy set by default).
* @param id Unique identifier.
* @param name An optional name for the meta data as a **string literal**.
* @return A meta factory for the parent type.
*/
template<auto Setter, auto Getter>
template<auto Setter, auto Getter, typename Policy = as_is_t>
meta_factory data(const id_type id, const char *name = nullptr) noexcept {
using descriptor = meta_function_helper_t<Type, decltype(Getter)>;
static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy");
if constexpr(std::is_same_v<decltype(Setter), std::nullptr_t>) {
base_type::data(
@@ -388,7 +403,7 @@ public:
&internal::resolve<std::remove_cv_t<std::remove_reference_t<typename descriptor::return_type>>>,
&meta_arg<type_list<>>,
&meta_setter<Type, Setter>,
&meta_getter<Type, Getter>});
&meta_getter<Type, Getter, Policy>});
} else {
using args_type = typename meta_function_helper_t<Type, decltype(Setter)>::args_type;
@@ -402,7 +417,7 @@ public:
&internal::resolve<std::remove_cv_t<std::remove_reference_t<typename descriptor::return_type>>>,
&meta_arg<type_list<type_list_element_t<static_cast<std::size_t>(args_type::size != 1u), args_type>>>,
&meta_setter<Type, Setter>,
&meta_getter<Type, Getter>});
&meta_getter<Type, Getter, Policy>});
}
return *this;
@@ -411,12 +426,13 @@ public:
/**
* @brief Assigns a meta function to a meta type.
* @tparam Candidate The actual function to attach to the meta function.
* @tparam Policy Optional policy (no policy set by default).
* @param name A custom unique identifier as a **string literal**.
* @return A meta factory for the given type.
*/
template<auto Candidate>
template<auto Candidate, typename Policy = as_is_t>
meta_factory func(const char *name) noexcept {
return func<Candidate>(entt::hashed_string::value(name), name);
return func<Candidate, Policy>(entt::hashed_string::value(name), name);
}
/**
@@ -428,13 +444,15 @@ public:
* reflected object will appear as if they were part of the type itself.
*
* @tparam Candidate The actual function to attach to the meta type.
* @tparam Policy Optional policy (no policy set by default).
* @param id Unique identifier.
* @param name An optional name for the function as a **string literal**.
* @return A meta factory for the parent type.
*/
template<auto Candidate>
template<auto Candidate, typename Policy = as_is_t>
meta_factory func(const id_type id, const char *name = nullptr) noexcept {
using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy");
base_type::func(
internal::meta_func_node{
@@ -442,9 +460,9 @@ public:
name,
(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::args_type::size,
&internal::resolve<std::remove_cv_t<std::remove_reference_t<typename descriptor::return_type>>>,
&internal::resolve<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, std::remove_cv_t<std::remove_reference_t<typename descriptor::return_type>>>>,
&meta_arg<typename descriptor::args_type>,
&meta_invoke<Type, Candidate>});
&meta_invoke<Type, Candidate, Policy>});
return *this;
}

58
src/entt/meta/policy.hpp Normal file
View File

@@ -0,0 +1,58 @@
#ifndef ENTT_META_POLICY_HPP
#define ENTT_META_POLICY_HPP
#include <type_traits>
namespace entt {
/*! @brief Empty class type used to request the _as ref_ policy. */
struct as_ref_t final {
/*! @cond TURN_OFF_DOXYGEN */
template<typename Type>
static constexpr bool value = std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>;
/*! @endcond */
};
/*! @brief Empty class type used to request the _as cref_ policy. */
struct as_cref_t final {
/*! @cond TURN_OFF_DOXYGEN */
template<typename Type>
static constexpr bool value = std::is_reference_v<Type>;
/*! @endcond */
};
/*! @brief Empty class type used to request the _as-is_ policy. */
struct as_is_t final {
/*! @cond TURN_OFF_DOXYGEN */
template<typename>
static constexpr bool value = true;
/*! @endcond */
};
/*! @brief Empty class type used to request the _as void_ policy. */
struct as_void_t final {
/*! @cond TURN_OFF_DOXYGEN */
template<typename>
static constexpr bool value = true;
/*! @endcond */
};
/**
* @brief Provides the member constant `value` to true if a type also is a meta
* policy, false otherwise.
* @tparam Type Type to check.
*/
template<typename Type>
struct is_meta_policy
: std::bool_constant<std::is_same_v<Type, as_ref_t> || std::is_same_v<Type, as_cref_t> || std::is_same_v<Type, as_is_t> || std::is_same_v<Type, as_void_t>> {};
/**
* @brief Helper variable template.
* @tparam Type Type to check.
*/
template<typename Type>
inline constexpr bool is_meta_policy_v = is_meta_policy<Type>::value;
} // namespace entt
#endif

View File

@@ -9,6 +9,7 @@
#include "../locator/locator.hpp"
#include "meta.hpp"
#include "node.hpp"
#include "policy.hpp"
namespace entt {
@@ -76,7 +77,7 @@ template<typename Type, typename Ret, typename Class>
struct meta_function_descriptor<Type, Ret Class::*>
: meta_function_descriptor_traits<
Ret &,
std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Ret>, type_list<Class &, Ret>>,
std::conditional_t<std::is_base_of_v<Class, Type>, type_list<>, type_list<Class &>>,
!std::is_base_of_v<Class, Type>,
false> {};
@@ -151,66 +152,73 @@ template<typename Type, typename Candidate>
using meta_function_helper_t = typename meta_function_helper<Type, Candidate>::type;
/**
* @brief Wraps a value and returns it.
* @brief Wraps a value depending on the given policy.
*
* This function always returns a wrapped value in the requested context.<br/>
* Therefore, if the passed value is itself a wrapped object with a different
* context, it undergoes a rebinding to the requested context.
*
* @tparam Policy Optional policy (no policy set by default).
* @tparam Type Type of value to wrap.
* @param ctx The context from which to search for meta types.
* @param value Value to wrap.
* @return A meta any containing the returned value, if any.
*/
template<typename Type>
[[nodiscard]] meta_any meta_dispatch(const meta_ctx &ctx, [[maybe_unused]] Type &&value) {
if constexpr(std::is_lvalue_reference_v<Type> && !std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, meta_any>) {
return meta_any{ctx, std::in_place_type<Type>, std::forward<Type>(value)};
template<typename Policy = as_is_t, typename Type>
[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_dispatch(const meta_ctx &ctx, [[maybe_unused]] Type &&value) {
if constexpr(std::is_same_v<Policy, as_void_t>) {
return meta_any{ctx, std::in_place_type<void>};
} else if constexpr(std::is_same_v<Policy, as_ref_t>) {
return meta_any{ctx, std::in_place_type<Type>, value};
} else if constexpr(std::is_same_v<Policy, as_cref_t>) {
static_assert(std::is_lvalue_reference_v<Type>, "Invalid type");
return meta_any{ctx, std::in_place_type<const std::remove_reference_t<Type> &>, std::as_const(value)};
} else {
return meta_any{ctx, std::forward<Type>(value)};
}
}
/**
* @brief Wraps a value and returns it.
* @brief Wraps a value depending on the given policy.
* @tparam Policy Optional policy (no policy set by default).
* @tparam Type Type of value to wrap.
* @param value Value to wrap.
* @return A meta any containing the returned value, if any.
*/
template<typename Type>
[[nodiscard]] meta_any meta_dispatch(Type &&value) {
return meta_dispatch<Type>(locator<meta_ctx>::value_or(), std::forward<Type>(value));
template<typename Policy = as_is_t, typename Type>
[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_dispatch(Type &&value) {
return meta_dispatch<Policy, Type>(locator<meta_ctx>::value_or(), std::forward<Type>(value));
}
/*! @cond TURN_OFF_DOXYGEN */
namespace internal {
template<typename Candidate, typename... Args>
template<typename Policy, typename Candidate, typename... Args>
[[nodiscard]] meta_any meta_invoke_with_args(const meta_ctx &ctx, Candidate &&candidate, Args &&...args) {
if constexpr(std::is_void_v<decltype(std::invoke(std::forward<Candidate>(candidate), args...))>) {
std::invoke(std::forward<Candidate>(candidate), args...);
return meta_any{ctx, std::in_place_type<void>};
} else {
return meta_dispatch(ctx, std::invoke(std::forward<Candidate>(candidate), args...));
return meta_dispatch<Policy>(ctx, std::invoke(std::forward<Candidate>(candidate), args...));
}
}
template<typename Type, typename Candidate, std::size_t... Index>
template<typename Type, typename Policy, typename Candidate, std::size_t... Index>
[[nodiscard]] meta_any meta_invoke(meta_handle &instance, Candidate &&candidate, [[maybe_unused]] meta_any *const args, std::index_sequence<Index...>) {
using descriptor = meta_function_helper_t<Type, std::remove_reference_t<Candidate>>;
// NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span)
if constexpr(std::is_invocable_v<std::remove_reference_t<Candidate>, const Type &, type_list_element_t<Index, typename descriptor::args_type>...>) {
if(const auto *const clazz = instance->try_cast<const Type>(); clazz && ((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
return meta_invoke_with_args(instance->context(), std::forward<Candidate>(candidate), *clazz, (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
return meta_invoke_with_args<Policy>(instance->context(), std::forward<Candidate>(candidate), *clazz, (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
}
} else if constexpr(std::is_invocable_v<std::remove_reference_t<Candidate>, Type &, type_list_element_t<Index, typename descriptor::args_type>...>) {
if(auto *const clazz = instance->try_cast<Type>(); clazz && ((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
return meta_invoke_with_args(instance->context(), std::forward<Candidate>(candidate), *clazz, (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
return meta_invoke_with_args<Policy>(instance->context(), std::forward<Candidate>(candidate), *clazz, (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
}
} else {
if(((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
return meta_invoke_with_args(instance->context(), std::forward<Candidate>(candidate), (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
return meta_invoke_with_args<Policy>(instance->context(), std::forward<Candidate>(candidate), (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
}
}
// NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
@@ -301,22 +309,23 @@ template<typename Type, auto Data>
* @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>
[[nodiscard]] meta_any meta_getter(meta_handle instance) {
template<typename Type, auto Data, typename Policy = as_is_t>
[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_getter(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_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(auto *clazz = instance->try_cast<Type>(); clazz) {
return internal::meta_invoke_with_args(instance->context(), Data, *clazz);
return meta_dispatch<Policy>(instance->context(), std::invoke(Data, *clazz));
}
}
if constexpr(std::is_invocable_v<decltype(Data), const Type &>) {
if(auto *fallback = instance->try_cast<const Type>(); fallback) {
return internal::meta_invoke_with_args(instance->context(), Data, *fallback);
return meta_dispatch<Policy>(instance->context(), std::invoke(Data, *fallback));
}
}
}
@@ -326,38 +335,40 @@ template<typename Type, auto Data>
if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) {
return meta_any{meta_ctx_arg, instance->context()};
} else {
return meta_dispatch(instance->context(), *Data);
return meta_dispatch<Policy>(instance->context(), *Data);
}
} else {
return meta_dispatch(instance->context(), Data);
return meta_dispatch<Policy>(instance->context(), Data);
}
}
/**
* @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 Candidate>
[[nodiscard]] meta_any meta_invoke(meta_handle instance, Candidate &&candidate, meta_any *const args) {
return internal::meta_invoke<Type>(instance, std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
template<typename Type, typename Policy = as_is_t, typename Candidate>
[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_invoke(meta_handle instance, Candidate &&candidate, meta_any *const args) {
return internal::meta_invoke<Type, Policy>(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 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>
[[nodiscard]] meta_any meta_invoke(meta_handle instance, meta_any *const args) {
return internal::meta_invoke<Type>(instance, Candidate, args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<decltype(Candidate)>>::args_type::size>{});
template<typename Type, auto Candidate, typename Policy = as_is_t>
[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_invoke(meta_handle instance, meta_any *const args) {
return internal::meta_invoke<Type, Policy>(instance, Candidate, args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<decltype(Candidate)>>::args_type::size>{});
}
/**
@@ -398,35 +409,37 @@ template<typename Type, typename... Args>
* It's up to the caller to bind the arguments to the right context(s).
*
* @tparam Type Reflected type to which the object to _invoke_ is associated.
* @tparam Policy Optional policy (no policy set by default).
* @tparam Candidate The type of the actual object to _invoke_.
* @param ctx The context from which to search for meta types.
* @param candidate The actual object to _invoke_.
* @param args Parameters to use to _invoke_ the object.
* @return A meta any containing the returned value, if any.
*/
template<typename Type, typename Candidate>
template<typename Type, typename Policy = as_is_t, typename Candidate>
[[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, 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>>>) {
meta_handle placeholder{meta_ctx_arg, ctx};
return internal::meta_invoke<Type>(placeholder, 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>(placeholder, std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
} else {
meta_handle target{*args};
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span)
return internal::meta_invoke<Type>(target, std::forward<Candidate>(candidate), args + 1u, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
return internal::meta_invoke<Type, Policy>(target, std::forward<Candidate>(candidate), args + 1u, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
}
}
/**
* @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 Candidate>
[[nodiscard]] meta_any meta_construct(Candidate &&candidate, meta_any *const args) {
return meta_construct<Type>(locator<meta_ctx>::value_or(), std::forward<Candidate>(candidate), args);
template<typename Type, typename Policy = as_is_t, typename Candidate>
[[nodiscard]] std::enable_if_t<is_meta_policy_v<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);
}
/**
@@ -438,25 +451,27 @@ template<typename Type, typename Candidate>
*
* @tparam Type Reflected type to which the function is associated.
* @tparam Candidate The actual function to invoke.
* @tparam Policy Optional policy (no policy set by default).
* @param ctx The context from which to search for meta types.
* @param args Parameters to use to invoke the function.
* @return A meta any containing the returned value, if any.
*/
template<typename Type, auto Candidate>
[[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, meta_any *const args) {
return meta_construct<Type>(ctx, Candidate, args);
template<typename Type, auto Candidate, typename Policy = as_is_t>
[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_construct(const meta_ctx &ctx, 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.
*/
template<typename Type, auto Candidate>
[[nodiscard]] meta_any meta_construct(meta_any *const args) {
return meta_construct<Type, Candidate>(locator<meta_ctx>::value_or(), args);
template<typename Type, auto Candidate, typename Policy = as_is_t>
[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_construct(meta_any *const args) {
return meta_construct<Type, Candidate, Policy>(locator<meta_ctx>::value_or(), args);
}
} // namespace entt

View File

@@ -7,6 +7,7 @@
#include <entt/meta/context.hpp>
#include <entt/meta/factory.hpp>
#include <entt/meta/meta.hpp>
#include <entt/meta/policy.hpp>
#include <entt/meta/resolve.hpp>
struct base {
@@ -59,7 +60,7 @@ struct MetaCtor: ::testing::Test {
entt::meta_factory<clazz>{}
.type("clazz"_hs)
.ctor<&entt::registry::emplace_or_replace<clazz, const int &, const char &>>()
.ctor<&entt::registry::emplace_or_replace<clazz, const int &, const char &>, entt::as_ref_t>()
.ctor<const base &, int &>()
.ctor<const int &, char>()
.ctor<entt::overload<clazz(int)>(clazz::factory)>()

View File

@@ -9,6 +9,7 @@
#include <entt/meta/factory.hpp>
#include <entt/meta/meta.hpp>
#include <entt/meta/node.hpp>
#include <entt/meta/policy.hpp>
#include <entt/meta/range.hpp>
#include <entt/meta/resolve.hpp>
#include "../../common/config.h"
@@ -66,17 +67,6 @@ struct array {
int local[4]; // NOLINT
};
// waiting for C++20 and lambdas inlined as template arguments
namespace {
const int &clazz_i_as_const_reference(const clazz &elem) {
return elem.i;
}
void clazz_i_as_void(const clazz &) {}
} // namespace
struct MetaData: ::testing::Test {
void SetUp() override {
using namespace entt::literals;
@@ -92,10 +82,10 @@ struct MetaData: ::testing::Test {
entt::meta_factory<clazz>{}
.type("clazz"_hs)
.data<&clazz::i>("i"_hs)
.data<&clazz::i, entt::as_ref_t>("i"_hs)
.custom<char>('c')
.traits(test::meta_traits::one | test::meta_traits::two | test::meta_traits::three)
.data<&clazz::i, &clazz_i_as_const_reference>("ci"_hs)
.data<&clazz::i, entt::as_cref_t>("ci"_hs)
.data<&clazz::j>("j")
.traits(test::meta_traits::one)
.data<&clazz::h>("h"_hs, "hhh")
@@ -104,7 +94,7 @@ struct MetaData: ::testing::Test {
.traits(test::meta_traits::three)
.data<'c'>("l"_hs)
.data<&clazz::instance>("base"_hs)
.data<&clazz::i, clazz_i_as_void>("void"_hs)
.data<&clazz::i, entt::as_void_t>("void"_hs)
.conv<int>();
entt::meta_factory<setter_getter>{}
@@ -544,7 +534,7 @@ TEST_F(MetaData, AsVoid) {
ASSERT_TRUE(data);
ASSERT_EQ(data.arity(), 1u);
ASSERT_EQ(data.type(), entt::resolve<void>());
ASSERT_EQ(data.type(), entt::resolve<int>());
ASSERT_EQ(data.arg(0u), entt::resolve<int>());
ASSERT_TRUE(data.set(instance, 1));
ASSERT_EQ(instance.i, 1);

View File

@@ -7,6 +7,7 @@
#include <entt/entity/registry.hpp>
#include <entt/meta/factory.hpp>
#include <entt/meta/meta.hpp>
#include <entt/meta/policy.hpp>
#include <entt/meta/range.hpp>
#include <entt/meta/resolve.hpp>
#include "../../common/config.h"
@@ -88,19 +89,6 @@ double double_member(const double &value) {
return value * value;
}
// waiting for C++20 and lambdas inlined as template arguments
namespace {
void elem_v_as_void(const function &elem, int &iv) {
static_cast<void>(elem.v(iv));
}
const int &elem_a_as_const(function &elem) {
return elem.a();
}
} // namespace
struct MetaFunc: ::testing::Test {
void SetUp() override {
using namespace entt::literals;
@@ -124,7 +112,7 @@ struct MetaFunc: ::testing::Test {
entt::meta_factory<function>{}
.type("func"_hs)
.func<&entt::registry::emplace_or_replace<function>>("emplace"_hs)
.func<&entt::registry::emplace_or_replace<function>, entt::as_ref_t>("emplace"_hs)
.traits(test::meta_traits::one | test::meta_traits::two | test::meta_traits::three)
.func<entt::overload<int(const base &, int, int)>(&function::f)>("f3"_hs)
.traits(test::meta_traits::three)
@@ -137,9 +125,9 @@ struct MetaFunc: ::testing::Test {
.custom<char>('c')
.func<function::h>("h"_hs)
.func<function::k>("k"_hs)
.func<&elem_v_as_void>("v"_hs)
.func<&function::a>("a"_hs)
.func<&elem_a_as_const>("ca"_hs)
.func<&function::v, entt::as_void_t>("v"_hs)
.func<&function::a, entt::as_ref_t>("a"_hs)
.func<&function::a, entt::as_cref_t>("ca"_hs)
.conv<int>();
}

View File

@@ -4,6 +4,7 @@
#include <gtest/gtest.h>
#include <entt/core/type_traits.hpp>
#include <entt/meta/meta.hpp>
#include <entt/meta/policy.hpp>
#include <entt/meta/resolve.hpp>
#include <entt/meta/utility.hpp>
#include "../../common/config.h"
@@ -58,20 +59,22 @@ using MetaUtilityDeathTest = MetaUtility;
TEST_F(MetaUtility, MetaDispatch) {
int value = 2;
auto as_ref = entt::meta_dispatch(value);
auto as_cref = entt::meta_dispatch(std::as_const(value));
auto as_copy = entt::meta_dispatch(static_cast<int &&>(value));
auto as_void = entt::meta_dispatch<entt::as_void_t>(value);
auto as_ref = entt::meta_dispatch<entt::as_ref_t>(value);
auto as_cref = entt::meta_dispatch<entt::as_cref_t>(value);
auto as_is = entt::meta_dispatch(value);
ASSERT_EQ(as_void.type(), entt::resolve<void>());
ASSERT_EQ(as_ref.type(), entt::resolve<int>());
ASSERT_EQ(as_cref.type(), entt::resolve<int>());
ASSERT_EQ(as_copy.type(), entt::resolve<int>());
ASSERT_EQ(as_is.type(), entt::resolve<int>());
ASSERT_NE(as_copy.try_cast<int>(), nullptr);
ASSERT_NE(as_is.try_cast<int>(), nullptr);
ASSERT_NE(as_ref.try_cast<int>(), nullptr);
ASSERT_EQ(as_cref.try_cast<int>(), nullptr);
ASSERT_NE(as_cref.try_cast<const int>(), nullptr);
ASSERT_EQ(as_copy.cast<int>(), 2);
ASSERT_EQ(as_is.cast<int>(), 2);
ASSERT_EQ(as_ref.cast<int>(), 2);
ASSERT_EQ(as_cref.cast<int>(), 2);
}

View File

@@ -5,6 +5,7 @@
#include <entt/entity/storage.hpp>
#include <entt/meta/factory.hpp>
#include <entt/meta/meta.hpp>
#include <entt/meta/policy.hpp>
#include <entt/meta/resolve.hpp>
enum class my_entity : entt::id_type {};
@@ -30,9 +31,9 @@ meta_mixin<Type>::meta_mixin(const allocator_type &allocator)
entt::meta_factory<element_type>{}
// cross registry, same type
.template func<entt::overload<entt::storage_for_t<element_type, entt::entity> &(const entt::id_type)>(&entt::basic_registry<entt::entity>::storage<element_type>)>("storage"_hs)
.template func<entt::overload<entt::storage_for_t<element_type, entt::entity> &(const entt::id_type)>(&entt::basic_registry<entt::entity>::storage<element_type>), entt::as_ref_t>("storage"_hs)
// cross registry, different types
.template func<entt::overload<entt::storage_for_t<element_type, my_entity> &(const entt::id_type)>(&entt::basic_registry<my_entity>::storage<element_type>)>("storage"_hs);
.template func<entt::overload<entt::storage_for_t<element_type, my_entity> &(const entt::id_type)>(&entt::basic_registry<my_entity>::storage<element_type>), entt::as_ref_t>("storage"_hs);
}
template<typename Type>