1#ifndef ENTT_META_FACTORY_HPP
2#define ENTT_META_FACTORY_HPP
10#include "../config/config.h"
11#include "../core/fwd.hpp"
12#include "../core/type_info.hpp"
13#include "../core/type_traits.hpp"
14#include "../locator/locator.hpp"
28[[nodiscard]]
inline decltype(
auto)
owner(meta_ctx &ctx,
const type_info &info) {
29 auto &&context = internal::meta_context::from(ctx);
30 ENTT_ASSERT(context.value.contains(info.hash()),
"Type not available");
31 return context.value[info.hash()];
34inline meta_data_node &meta_extend(internal::meta_type_node &parent,
const id_type
id, meta_data_node node) {
35 return parent.details->data.insert_or_assign(
id, std::move(node)).first->second;
38inline meta_func_node &meta_extend(internal::meta_type_node &parent,
const id_type
id, meta_func_node node) {
39 if(
auto it = parent.details->func.find(
id); it != parent.details->func.end()) {
40 for(
auto *curr = &it->second; curr; curr = curr->next.get()) {
41 if(curr->invoke == node.invoke) {
42 node.next = std::move(curr->next);
43 *curr = std::move(node);
49 node.next = std::make_shared<meta_func_node>(std::move(parent.details->func[
id]));
52 return parent.details->func.insert_or_assign(
id, std::move(node)).first->second;
62template<
typename Type>
64 template<
typename Setter,
auto Getter,
typename Policy, std::size_t... Index>
65 void data(
const id_type id, std::index_sequence<Index...>)
noexcept {
66 using data_type = std::invoke_result_t<
decltype(Getter), Type &>;
68 static_assert(Policy::template value<data_type>,
"Invalid return type for the given policy");
70 auto &&elem = internal::meta_extend(
71 internal::owner(*ctx, *info),
73 internal::meta_data_node{
75 (std::is_member_object_pointer_v<
decltype(value_list_element_v<Index, Setter>)> && ... && std::is_const_v<std::remove_reference_t<data_type>>) ? internal::meta_traits::is_const : internal::meta_traits::is_none,
77 &internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>,
80 &meta_getter<Type, Getter, Policy>});
97 info{&type_id<Type>()} {
98 auto &&elem = internal::owner(*ctx, *info);
101 elem.details = std::make_shared<internal::meta_type_descriptor>();
104 bucket = &elem.details->prop;
113 auto &&elem = internal::owner(*ctx, *info);
114 ENTT_ASSERT(elem.id ==
id || !
resolve(*ctx,
id),
"Duplicate identifier");
115 bucket = &elem.details->prop;
128 template<
typename Base>
130 static_assert(!std::is_same_v<Type, Base> && std::is_base_of_v<Base, Type>,
"Invalid base type");
131 auto *
const op = +[](
const void *instance)
noexcept {
return static_cast<const void *
>(
static_cast<const Base *
>(
static_cast<const Type *
>(instance))); };
132 internal::owner(*ctx, *info).details->base.insert_or_assign(type_id<Base>().hash(), internal::meta_base_node{&internal::resolve<Base>, op});
149 template<auto Cand
idate>
151 using conv_type = std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<
decltype(Candidate), Type &>>>;
152 auto *
const op = +[](
const meta_ctx &area,
const void *instance) {
return forward_as_meta(area, std::invoke(Candidate, *
static_cast<const Type *
>(instance))); };
153 internal::owner(*ctx, *info).details->conv.insert_or_assign(type_id<conv_type>().hash(), internal::meta_conv_node{op});
167 template<
typename To>
169 using conv_type = std::remove_cv_t<std::remove_reference_t<To>>;
170 auto *
const op = +[](
const meta_ctx &area,
const void *instance) {
return forward_as_meta(area,
static_cast<To
>(*
static_cast<const Type *
>(instance))); };
171 internal::owner(*ctx, *info).details->conv.insert_or_assign(type_id<conv_type>().hash(), internal::meta_conv_node{op});
189 template<auto Cand
idate,
typename Policy = as_is_t>
192 static_assert(Policy::template value<typename descriptor::return_type>,
"Invalid return type for the given policy");
193 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");
194 internal::owner(*ctx, *info).details->ctor.insert_or_assign(type_id<typename descriptor::args_type>().hash(), internal::meta_ctor_node{descriptor::args_type::size, &meta_arg<typename descriptor::args_type>, &meta_construct<Type, Candidate, Policy>});
209 template<
typename... Args>
212 if constexpr(
sizeof...(Args) != 0u) {
214 internal::owner(*ctx, *info).details->ctor.insert_or_assign(type_id<typename descriptor::args_type>().hash(), internal::meta_ctor_node{descriptor::args_type::size, &meta_arg<typename descriptor::args_type>, &
meta_construct<Type, Args...>});
241 static_assert(std::is_invocable_v<
decltype(Func), Type &>,
"The function doesn't accept an object of the type provided");
242 auto *
const op = +[](
void *instance) { std::invoke(Func, *
static_cast<Type *
>(instance)); };
243 internal::owner(*ctx, *info).dtor = internal::meta_dtor_node{op};
261 template<auto Data,
typename Policy = as_is_t>
263 if constexpr(std::is_member_object_pointer_v<
decltype(Data)>) {
264 using data_type = std::invoke_result_t<
decltype(Data), Type &>;
265 static_assert(Policy::template value<data_type>,
"Invalid return type for the given policy");
267 auto &&elem = internal::meta_extend(
268 internal::owner(*ctx, *info),
270 internal::meta_data_node{
272 std::is_const_v<std::remove_reference_t<data_type>> ? internal::meta_traits::is_const : internal::meta_traits::is_none,
274 &internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>,
275 &meta_arg<type_list<std::remove_cv_t<std::remove_reference_t<data_type>>>>,
276 &meta_setter<Type, Data>,
277 &meta_getter<Type, Data, Policy>});
281 using data_type = std::remove_pointer_t<
decltype(Data)>;
283 if constexpr(std::is_pointer_v<
decltype(Data)>) {
284 static_assert(Policy::template value<
decltype(*Data)>,
"Invalid return type for the given policy");
286 static_assert(Policy::template value<data_type>,
"Invalid return type for the given policy");
289 auto &&elem = internal::meta_extend(
290 internal::owner(*ctx, *info),
292 internal::meta_data_node{
293 ((std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<data_type>>> || std::is_const_v<std::remove_reference_t<data_type>>) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static,
295 &internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>,
296 &meta_arg<
type_list<std::remove_cv_t<std::remove_reference_t<data_type>>>>,
297 &meta_setter<Type, Data>,
298 &meta_getter<Type, Data, Policy>});
326 template<auto Setter, auto Getter,
typename Policy = as_is_t>
328 using data_type = std::invoke_result_t<
decltype(Getter), Type &>;
329 static_assert(Policy::template value<data_type>,
"Invalid return type for the given policy");
331 if constexpr(std::is_same_v<
decltype(Setter), std::nullptr_t>) {
332 auto &&elem = internal::meta_extend(
333 internal::owner(*ctx, *info),
335 internal::meta_data_node{
337 internal::meta_traits::is_const,
339 &internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>,
340 &meta_arg<type_list<>>,
341 &meta_setter<Type, Setter>,
342 &meta_getter<Type, Getter, Policy>});
348 auto &&elem = internal::meta_extend(
349 internal::owner(*ctx, *info),
351 internal::meta_data_node{
353 internal::meta_traits::is_none,
355 &internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>,
356 &meta_arg<type_list<type_list_element_t<args_type::size != 1u, args_type>>>,
357 &meta_setter<Type, Setter>,
358 &meta_getter<Type, Getter, Policy>});
383 template<
typename Setter, auto Getter,
typename Policy = as_is_t>
385 data<Setter, Getter, Policy>(
id, std::make_index_sequence<Setter::size>{});
402 template<auto Cand
idate,
typename Policy = as_is_t>
405 static_assert(Policy::template value<typename descriptor::return_type>,
"Invalid return type for the given policy");
407 auto &&elem = internal::meta_extend(
408 internal::owner(*ctx, *info),
410 internal::meta_func_node{
411 (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),
412 descriptor::args_type::size,
413 &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>>>>,
414 &meta_arg<typename descriptor::args_type>,
415 &meta_invoke<Type, Candidate, Policy>});
431 template<
typename... Value>
433 ENTT_ASSERT(bucket !=
nullptr,
"Meta object does not support properties");
435 if constexpr(
sizeof...(Value) == 0u) {
436 (*bucket)[id] = internal::meta_prop_node{&internal::resolve<void>};
438 (*bucket)[id] = internal::meta_prop_node{
439 &internal::resolve<std::decay_t<Value>>...,
440 std::make_shared<std::decay_t<Value>>(std::forward<Value>(value))...};
464template<
typename Type>
466 auto &&context = internal::meta_context::from(ctx);
468 context.value.try_emplace(type_id<Type>().hash(), internal::resolve<Type>(context));
483template<
typename Type>
484[[nodiscard]]
auto meta() noexcept {
501 auto &&context = internal::meta_context::from(ctx);
503 for(
auto it = context.value.begin(); it != context.value.end();) {
504 if(it->second.id ==
id) {
505 it = context.value.erase(it);
535template<
typename Type>
537 internal::meta_context::from(ctx).value.erase(type_id<Type>().hash());
547template<
typename Type>
560 internal::meta_context::from(ctx).value.clear();
Associative container for key-value pairs with unique keys.
Service locator, nothing more.
static Service & value_or(Args &&...args)
Returns a service if available or sets it from a fallback type.
std::uint32_t id_type
Alias declaration for type identifiers.
meta_any meta_construct(const meta_ctx &ctx, meta_any *const args)
Tries to construct an instance given a list of erased parameters.
typename meta_function_helper< Type, Candidate >::type meta_function_helper_t
Helper type.
auto meta() noexcept
Utility function to use for reflection.
meta_type resolve() noexcept
Returns the meta type associated with a given type.
void meta_reset() noexcept
Resets a type and all its parts.
meta_any forward_as_meta(const meta_ctx &ctx, Type &&value)
Forwards its argument and avoids copies for lvalue references.
bool meta_setter(meta_handle instance, meta_any value)
Sets the value of a given variable.
typename type_list_element< Index, List >::type type_list_element_t
Helper type.
@ owner
Default mode, the object owns the contained element.
Implementation specific information about a type.
A class to use to push around lists of types, nothing more.