1#ifndef ENTT_META_UTILITY_HPP
2#define ENTT_META_UTILITY_HPP
8#include "../core/type_traits.hpp"
9#include "../locator/locator.hpp"
23template<
typename Ret,
typename Args,
bool Static,
bool Const>
37template<
typename,
typename>
47template<
typename Type,
typename Ret,
typename Class,
typename... Args>
51 std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<const Class &, Args...>>,
52 !std::is_base_of_v<Class, Type>,
62template<
typename Type,
typename Ret,
typename Class,
typename... Args>
66 std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<Class &, Args...>>,
67 !std::is_base_of_v<Class, Type>,
76template<
typename Type,
typename Ret,
typename Class>
80 std::conditional_t<std::is_base_of_v<Class, Type>, type_list<>, type_list<Class &>>,
81 !std::is_base_of_v<Class, Type>,
91template<
typename Type,
typename Ret,
typename MaybeType,
typename... Args>
96 std::is_same_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type> || std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type>,
99 !(std::is_same_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type> || std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type>),
100 std::is_const_v<std::remove_reference_t<MaybeType>> && (std::is_same_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type> || std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type>)> {};
107template<
typename Type,
typename Ret>
124template<
typename Type,
typename Cand
idate>
126 template<
typename Ret,
typename... Args,
typename Class>
127 static constexpr meta_function_descriptor<Type, Ret (Class::*)(Args...)
const> get_rid_of_noexcept(Ret (Class::*)(Args...)
const);
129 template<
typename Ret,
typename... Args,
typename Class>
130 static constexpr meta_function_descriptor<Type, Ret (Class::*)(Args...)> get_rid_of_noexcept(Ret (Class::*)(Args...));
132 template<
typename Ret,
typename Class,
typename = std::enable_if_t<std::is_member_
object_po
inter_v<Ret Class::*>>>
135 template<
typename Ret,
typename... Args>
138 template<
typename Class>
143 using type =
decltype(get_rid_of_noexcept(std::declval<Candidate>()));
151template<
typename Type,
typename Cand
idate>
167template<
typename Policy = as_is_t,
typename Type>
169 if constexpr(std::is_same_v<Policy, as_void_t>) {
170 return meta_any{ctx, std::in_place_type<void>};
171 }
else if constexpr(std::is_same_v<Policy, as_ref_t>) {
172 return meta_any{ctx, std::in_place_type<Type>, value};
173 }
else if constexpr(std::is_same_v<Policy, as_cref_t>) {
174 static_assert(std::is_lvalue_reference_v<Type>,
"Invalid type");
175 return meta_any{ctx, std::in_place_type<const std::remove_reference_t<Type> &>, std::as_const(value)};
177 return meta_any{ctx, std::forward<Type>(value)};
188template<
typename Policy = as_is_t,
typename Type>
196template<
typename Policy,
typename Candidate,
typename... Args>
197[[nodiscard]] meta_any meta_invoke_with_args(
const meta_ctx &ctx, Candidate &&candidate, Args &&...args) {
198 if constexpr(std::is_void_v<decltype(std::invoke(std::forward<Candidate>(candidate), args...))>) {
199 std::invoke(std::forward<Candidate>(candidate), args...);
200 return meta_any{ctx, std::in_place_type<void>};
202 return meta_dispatch<Policy>(ctx, std::invoke(std::forward<Candidate>(candidate), args...));
206template<
typename Type,
typename Policy,
typename Candidate, std::size_t... Index>
207[[nodiscard]] meta_any
meta_invoke(meta_handle instance, Candidate &&candidate, [[maybe_unused]] meta_any *
const args, std::index_sequence<Index...>) {
208 using descriptor = meta_function_helper_t<Type, std::remove_reference_t<Candidate>>;
211 if constexpr(std::is_invocable_v<std::remove_reference_t<Candidate>,
const Type &, type_list_element_t<Index, typename descriptor::args_type>...>) {
212 if(
const auto *
const clazz = instance->try_cast<
const Type>(); clazz && ((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
213 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>>()...);
215 }
else if constexpr(std::is_invocable_v<std::remove_reference_t<Candidate>, Type &, type_list_element_t<Index, typename descriptor::args_type>...>) {
216 if(
auto *
const clazz = instance->try_cast<Type>(); clazz && ((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
217 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>>()...);
220 if(((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
221 return meta_invoke_with_args<Policy>(instance->context(), std::forward<Candidate>(candidate), (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
229template<
typename Type,
typename... Args, std::size_t... Index>
230[[nodiscard]] meta_any
meta_construct(
const meta_ctx &ctx, meta_any *
const args, std::index_sequence<Index...>) {
232 if(((args + Index)->allow_cast<Args>() && ...)) {
233 return meta_any{ctx, std::in_place_type<Type>, (args + Index)->cast<Args>()...};
250template<
typename Type>
251[[nodiscard]]
static meta_type meta_arg(
const meta_ctx &ctx,
const std::size_t index)
noexcept {
252 auto &&context = internal::meta_context::from(ctx);
253 return {ctx, internal::meta_arg_node(context, Type{}, index)};
262template<
typename Type>
263[[nodiscard]]
static meta_type meta_arg(
const std::size_t index)
noexcept {
275template<
typename Type, auto Data>
277 if constexpr(std::is_member_function_pointer_v<
decltype(Data)> || std::is_function_v<std::remove_reference_t<std::remove_pointer_t<
decltype(Data)>>>) {
281 if(
auto *
const clazz = instance->try_cast<Type>(); clazz && value.allow_cast<data_type>()) {
282 std::invoke(Data, *clazz, value.cast<data_type>());
285 }
else if constexpr(std::is_member_object_pointer_v<
decltype(Data)>) {
286 using data_type = std::remove_reference_t<
typename meta_function_helper_t<Type,
decltype(Data)>::return_type>;
288 if constexpr(!std::is_array_v<data_type> && !std::is_const_v<data_type>) {
289 if(
auto *
const clazz = instance->try_cast<Type>(); clazz && value.allow_cast<data_type>()) {
290 std::invoke(Data, *clazz) = value.cast<data_type>();
294 }
else if constexpr(std::is_pointer_v<
decltype(Data)>) {
295 using data_type = std::remove_reference_t<
decltype(*Data)>;
297 if constexpr(!std::is_array_v<data_type> && !std::is_const_v<data_type>) {
298 if(value.allow_cast<data_type>()) {
299 *Data = value.cast<data_type>();
316template<
typename Type, auto Data,
typename Policy = as_is_t>
318 if constexpr(std::is_member_pointer_v<
decltype(Data)> || std::is_function_v<std::remove_reference_t<std::remove_pointer_t<
decltype(Data)>>>) {
319 if constexpr(!std::is_array_v<std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<
decltype(Data), Type &>>>>) {
320 if constexpr(std::is_invocable_v<
decltype(Data), Type &>) {
321 if(
auto *clazz = instance->
try_cast<Type>(); clazz) {
326 if constexpr(std::is_invocable_v<
decltype(Data),
const Type &>) {
327 if(
auto *fallback = instance->
try_cast<
const Type>(); fallback) {
334 }
else if constexpr(std::is_pointer_v<
decltype(Data)>) {
335 if constexpr(std::is_array_v<std::remove_pointer_t<
decltype(Data)>>) {
354template<
typename Type, auto Data,
typename Policy = as_is_t>
355[[deprecated(
"a context is no longer required, it is inferred from the meta_handle")]] [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>,
meta_any>
meta_getter(
const meta_ctx &ctx,
meta_handle instance) {
369template<
typename Type,
typename Policy = as_is_t,
typename Cand
idate>
371 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>{});
385template<
typename Type,
typename Policy = as_is_t,
typename Cand
idate>
386[[deprecated(
"a context is no longer required, it is inferred from the meta_handle")]] [[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>,
meta_any>
meta_invoke(
const meta_ctx &ctx,
meta_handle instance, Candidate &&candidate,
meta_any *
const args) {
399template<
typename Type, auto Cand
idate,
typename Policy = as_is_t>
401 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>{});
414template<
typename Type, auto Cand
idate,
typename Policy = as_is_t>
432template<
typename Type,
typename... Args>
434 return internal::meta_construct<Type, Args...>(ctx, args, std::index_sequence_for<Args...>{});
444template<
typename Type,
typename... Args>
464template<
typename Type,
typename Policy = as_is_t,
typename Cand
idate>
467 return internal::meta_invoke<Type, Policy>(
meta_handle{
meta_ctx_arg, ctx}, std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
471 return internal::meta_invoke<Type, Policy>(
handle, std::forward<Candidate>(candidate), args + 1u, std::make_index_sequence<
meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{});
484template<
typename Type,
typename Policy = as_is_t,
typename Cand
idate>
503template<
typename Type, auto Cand
idate,
typename Policy = as_is_t>
516template<
typename Type, auto Cand
idate,
typename Policy = as_is_t>
static Service & value_or(Args &&...args)
Returns a service if available or sets it from a fallback type.
typename meta_function_helper< Type, Candidate >::type meta_function_helper_t
Helper type.
basic_handle< registry > handle
Alias declaration for the most common use case.
std::enable_if_t< is_meta_policy_v< Policy >, meta_any > meta_getter(meta_handle instance)
Gets the value of a given variable.
meta_any meta_construct(const meta_ctx &ctx, meta_any *const args)
Tries to construct an instance given a list of erased parameters.
std::enable_if_t< is_meta_policy_v< Policy >, meta_any > meta_invoke(meta_handle instance, Candidate &&candidate, meta_any *const args)
Tries to invoke an object given a list of erased parameters.
std::enable_if_t< is_meta_policy_v< Policy >, meta_any > meta_dispatch(const meta_ctx &ctx, Type &&value)
Wraps a value depending on the given policy.
typename type_list_element< Index, List >::type type_list_element_t
Helper type.
constexpr meta_ctx_arg_t meta_ctx_arg
Constant of type meta_context_arg_t used to disambiguate calls.
bool meta_setter(meta_handle instance, meta_any value)
Sets the value of a given variable.
A class to use to push around lists of types, nothing more.