1#ifndef ENTT_META_UTILITY_HPP
2#define ENTT_META_UTILITY_HPP
4#include "../core/type_traits.hpp"
5#include "../locator/locator.hpp"
6#include "../stl/cstddef.hpp"
7#include "../stl/functional.hpp"
8#include "../stl/type_traits.hpp"
9#include "../stl/utility.hpp"
23template<
typename Ret,
typename Args,
bool Static,
bool Const>
37template<
typename,
typename>
47template<
typename Type,
typename Ret,
typename Class,
typename... Args>
51 stl::conditional_t<stl::is_base_of_v<Class, Type>, type_list<Args...>, type_list<const Class &, Args...>>,
52 !stl::is_base_of_v<Class, Type>,
62template<
typename Type,
typename Ret,
typename Class,
typename... Args>
66 stl::conditional_t<stl::is_base_of_v<Class, Type>, type_list<Args...>, type_list<Class &, Args...>>,
67 !stl::is_base_of_v<Class, Type>,
76template<
typename Type,
typename Ret,
typename Class>
80 stl::conditional_t<stl::is_base_of_v<Class, Type>, type_list<>, type_list<Class &>>,
81 !stl::is_base_of_v<Class, Type>,
91template<
typename Type,
typename Ret,
typename MaybeType,
typename... Args>
96 stl::is_same_v<stl::remove_cvref_t<MaybeType>, Type> || stl::is_base_of_v<stl::remove_cvref_t<MaybeType>, Type>,
99 !(stl::is_same_v<stl::remove_cvref_t<MaybeType>, Type> || stl::is_base_of_v<stl::remove_cvref_t<MaybeType>, Type>),
100 stl::is_const_v<stl::remove_reference_t<MaybeType>> && (stl::is_same_v<stl::remove_cvref_t<MaybeType>, Type> || stl::is_base_of_v<stl::remove_cvref_t<MaybeType>, Type>)> {};
107template<
typename Type,
typename Ret>
124template<
typename Type,
typename Cand
idate>
126 template<
typename Ret,
typename... Args,
typename Class>
127 static meta_function_descriptor<Type, Ret (Class::*)(Args...)
const> get_rid_of_noexcept(Ret (Class::*)(Args...)
const);
129 template<
typename Ret,
typename... Args,
typename Class>
132 template<
typename Ret,
typename Class>
133 requires stl::is_member_object_pointer_v<Ret Class::*>
136 template<
typename Ret,
typename... Args>
139 template<
typename Class>
144 using type =
decltype(get_rid_of_noexcept(stl::declval<Candidate>()));
152template<
typename Type,
typename Cand
idate>
168template<meta_policy Policy = as_value_t,
typename Type>
170 if constexpr(stl::is_same_v<Policy, as_cref_t>) {
171 static_assert(stl::is_lvalue_reference_v<Type>,
"Invalid type");
172 return meta_any{ctx, stl::in_place_type<const stl::remove_reference_t<Type> &>, stl::as_const(value)};
173 }
else if constexpr(stl::is_same_v<Policy, as_ref_t> || (stl::is_same_v<Policy, as_is_t> && stl::is_lvalue_reference_v<Type>)) {
174 return meta_any{ctx, stl::in_place_type<Type>, value};
175 }
else if constexpr(stl::is_same_v<Policy, as_void_t>) {
176 return meta_any{ctx, stl::in_place_type<void>};
178 return meta_any{ctx, stl::forward<Type>(value)};
189template<meta_policy Policy = as_value_t,
typename Type>
197template<
typename Policy,
typename Candidate,
typename... Args>
198[[nodiscard]] meta_any meta_invoke_with_args(
const meta_ctx &ctx, Candidate &&candidate, Args &&...args) {
199 if constexpr(stl::is_void_v<decltype(stl::invoke(stl::forward<Candidate>(candidate), args...))>) {
200 stl::invoke(stl::forward<Candidate>(candidate), args...);
201 return meta_any{ctx, stl::in_place_type<void>};
203 return meta_dispatch<Policy>(ctx, stl::invoke(stl::forward<Candidate>(candidate), args...));
207template<
typename Type,
typename Policy,
typename Candidate, stl::size_t... Index>
208[[nodiscard]] meta_any
meta_invoke(meta_any &instance, Candidate &&candidate, [[maybe_unused]] meta_any *
const args, stl::index_sequence<Index...>) {
209 using descriptor = meta_function_helper_t<Type, stl::remove_reference_t<Candidate>>;
212 if constexpr(stl::is_invocable_v<stl::remove_reference_t<Candidate>,
const Type &, type_list_element_t<Index, typename descriptor::args_type>...>) {
213 if(
const auto *
const clazz = instance.try_cast<
const Type>(); clazz && ((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
214 return meta_invoke_with_args<Policy>(instance.context(), stl::forward<Candidate>(candidate), *clazz, (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
216 }
else if constexpr(stl::is_invocable_v<stl::remove_reference_t<Candidate>, Type &, type_list_element_t<Index, typename descriptor::args_type>...>) {
217 if(
auto *
const clazz = instance.try_cast<Type>(); clazz && ((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
218 return meta_invoke_with_args<Policy>(instance.context(), stl::forward<Candidate>(candidate), *clazz, (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
221 if(((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) {
222 return meta_invoke_with_args<Policy>(instance.context(), stl::forward<Candidate>(candidate), (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...);
230template<
typename Type,
typename... Args, stl::size_t... Index>
231[[nodiscard]] meta_any
meta_construct(
const meta_ctx &ctx, meta_any *
const args, stl::index_sequence<Index...>) {
233 if(((args + Index)->allow_cast<Args>() && ...)) {
234 return meta_any{ctx, stl::in_place_type<Type>, (args + Index)->cast<Args>()...};
251template<
typename Type>
253 const auto &context = internal::meta_context::from(ctx);
254 return {ctx, internal::meta_arg_node(context, Type{}, index)};
263template<
typename Type>
276template<
typename Type, auto Data>
278 if constexpr(stl::is_member_function_pointer_v<
decltype(Data)> || stl::is_function_v<stl::remove_reference_t<stl::remove_pointer_t<
decltype(Data)>>>) {
279 return static_cast<bool>(internal::meta_invoke<Type, as_void_t>(*instance.operator->(), Data, args, stl::make_index_sequence<
meta_function_helper_t<Type,
decltype(Data)>::args_type::size>{}));
280 }
else if constexpr(stl::is_member_object_pointer_v<
decltype(Data)>) {
281 using data_type = stl::remove_reference_t<
typename meta_function_helper_t<Type,
decltype(Data)>::return_type>;
283 if constexpr(!stl::is_array_v<data_type> && !stl::is_const_v<data_type>) {
284 if(
auto *
const clazz = instance->try_cast<Type>(); clazz && args->allow_cast<data_type>()) {
285 stl::invoke(Data, *clazz) = args->cast<data_type>();
291 }
else if constexpr(stl::is_pointer_v<
decltype(Data)>) {
292 using data_type = stl::remove_reference_t<
decltype(*Data)>;
294 if constexpr(!stl::is_array_v<data_type> && !stl::is_const_v<data_type>) {
295 if(args->allow_cast<data_type>()) {
296 *Data = args->cast<data_type>();
315template<
typename Type, auto Data>
329template<
typename Type, auto Data, meta_policy Policy = as_value_t>
331 if constexpr(stl::is_member_function_pointer_v<
decltype(Data)> || stl::is_function_v<stl::remove_reference_t<stl::remove_pointer_t<
decltype(Data)>>>) {
332 return internal::meta_invoke<Type, Policy>(*instance.operator->(), Data, args, stl::make_index_sequence<
meta_function_helper_t<Type,
decltype(Data)>::args_type::size>{});
333 }
else if constexpr(stl::is_member_object_pointer_v<
decltype(Data)>) {
334 if constexpr(!stl::is_array_v<stl::remove_cvref_t<stl::invoke_result_t<
decltype(Data), Type &>>>) {
335 if(
auto *clazz = instance->
try_cast<Type>(); clazz) {
337 }
else if(
auto *fallback = instance->
try_cast<
const Type>(); fallback) {
343 }
else if constexpr(stl::is_pointer_v<
decltype(Data)>) {
344 if constexpr(stl::is_array_v<stl::remove_pointer_t<
decltype(Data)>>) {
362template<
typename Type, auto Data, meta_policy Policy = as_value_t>
377template<
typename Type, meta_policy Policy = as_value_t,
typename Cand
idate>
379 return internal::meta_invoke<Type, Policy>(*instance.operator->(), stl::forward<Candidate>(candidate), args, stl::make_index_sequence<
meta_function_helper_t<Type, stl::remove_reference_t<Candidate>>::args_type::size>{});
391template<
typename Type, auto Cand
idate, meta_policy Policy = as_value_t>
393 return internal::meta_invoke<Type, Policy>(*instance.operator->(), Candidate, args, stl::make_index_sequence<
meta_function_helper_t<Type, stl::remove_reference_t<
decltype(Candidate)>>::args_type::size>{});
409template<
typename Type,
typename... Args>
411 return internal::meta_construct<Type, Args...>(ctx, args, stl::index_sequence_for<Args...>{});
421template<
typename Type,
typename... Args>
441template<
typename Type,
typename Policy = as_value_t,
typename Cand
idate>
445 return internal::meta_invoke<Type, Policy>(placeholder, stl::forward<Candidate>(candidate), args, stl::make_index_sequence<
meta_function_helper_t<Type, stl::remove_reference_t<Candidate>>::args_type::size>{});
448 return internal::meta_invoke<Type, Policy>(*args, stl::forward<Candidate>(candidate), args + 1u, stl::make_index_sequence<
meta_function_helper_t<Type, stl::remove_reference_t<Candidate>>::args_type::size>{});
461template<
typename Type, meta_policy Policy = as_value_t,
typename Cand
idate>
480template<
typename Type, auto Cand
idate, meta_policy Policy = as_value_t>
493template<
typename Type, auto Cand
idate, meta_policy Policy = as_value_t>
static Service & value_or(Args &&...args)
Returns a service if available or sets it from a fallback type.
meta_function_helper< Type, Candidate >::type meta_function_helper_t
Helper type.
meta_any meta_construct(const meta_ctx &ctx, meta_any *const args)
Tries to construct an instance given a list of erased parameters.
meta_any meta_invoke(meta_handle instance, Candidate &&candidate, meta_any *const args)
Tries to invoke an object given a list of erased parameters.
meta_any meta_dispatch(const meta_ctx &ctx, Type &&value)
Wraps a value depending on the given policy.
constexpr meta_ctx_arg_t meta_ctx_arg
Constant of type meta_context_arg_t used to disambiguate calls.
meta_type meta_arg(const meta_ctx &ctx, const stl::size_t index) noexcept
Returns the meta type of the i-th element of a list of arguments.
meta_any meta_getter(meta_handle instance, meta_any *const args)
Gets the value of a given variable.
bool meta_setter(meta_handle instance, meta_any *const args)
Sets the value of a given variable.
A class to use to push around lists of types, nothing more.