1#ifndef ENTT_META_FACTORY_HPP
2#define ENTT_META_FACTORY_HPP
11#include "../config/config.h"
12#include "../core/bit.hpp"
13#include "../core/fwd.hpp"
14#include "../core/hashed_string.hpp"
15#include "../core/type_info.hpp"
16#include "../core/type_traits.hpp"
17#include "../locator/locator.hpp"
32class basic_meta_factory {
33 using invoke_type = std::remove_pointer_t<
decltype(meta_func_node::invoke)>;
35 [[nodiscard]]
auto &fetch_node() noexcept {
36 return *meta_context::from(*ctx).value[parent];
39 [[nodiscard]]
auto *find_member_or_assert() {
40 auto *member = find_member<&meta_data_node::id>(fetch_node().details->data, bucket);
41 ENTT_ASSERT(member !=
nullptr,
"Cannot find member");
45 [[nodiscard]]
auto *find_overload_or_assert() {
46 auto *
overload = find_overload(find_member<&meta_func_node::id>(fetch_node().details->func, bucket), invoke);
47 ENTT_ASSERT(overload !=
nullptr,
"Cannot find overload");
51 void reset_bucket(
const id_type
id, invoke_type *
const ref =
nullptr) {
57 void type(
const id_type
id,
const char *name)
noexcept {
59 auto &elem = fetch_node();
60 ENTT_ASSERT(elem.id ==
id || !
resolve(*ctx,
id),
"Duplicate identifier");
65 template<
typename Type>
66 void insert_or_assign(Type node) {
67 auto &elem = fetch_node();
71 if constexpr(std::is_same_v<Type, meta_base_node>) {
72 auto *member = find_member<&meta_base_node::type>(elem.details->base, node.type);
73 member ? (*member = node) : elem.details->base.emplace_back(node);
74 }
else if constexpr(std::is_same_v<Type, meta_conv_node>) {
75 auto *member = find_member<&meta_conv_node::type>(elem.details->conv, node.type);
76 member ? (*member = node) : elem.details->conv.emplace_back(node);
78 static_assert(std::is_same_v<Type, meta_ctor_node>,
"Unexpected type");
79 auto *member = find_member<&meta_ctor_node::id>(elem.details->ctor, node.id);
80 member ? (*member = node) : elem.details->ctor.emplace_back(node);
84 void data(meta_data_node node) {
85 auto &elem = fetch_node();
87 reset_bucket(node.id);
89 if(
auto *member = find_member<&meta_data_node::id>(elem.details->data, node.id); member ==
nullptr) {
90 elem.details->data.emplace_back(std::move(node));
91 }
else if(member->set != node.set || member->get != node.get) {
92 *member = std::move(node);
96 void func(meta_func_node node) {
97 auto &elem = fetch_node();
99 reset_bucket(node.id, node.invoke);
101 if(
auto *member = find_member<&meta_func_node::id>(elem.details->func, node.id); member ==
nullptr) {
102 elem.details->func.emplace_back(std::move(node));
103 }
else if(
auto *overload = find_overload(member, node.invoke); overload ==
nullptr) {
104 while(member->next !=
nullptr) { member = member->next.get(); }
105 member->next = std::make_unique<meta_func_node>(std::move(node));
109 void traits(
const meta_traits value,
const bool unset) {
110 auto set_or_unset_on = [=](
auto &node) {
111 node.traits = (unset ? (node.traits & ~value) : (node.traits | value));
114 if(bucket == parent) {
115 set_or_unset_on(fetch_node());
116 }
else if(invoke ==
nullptr) {
117 set_or_unset_on(*find_member_or_assert());
119 set_or_unset_on(*find_overload_or_assert());
123 void custom(meta_custom_node node) {
124 if(bucket == parent) {
125 fetch_node().custom = std::move(node);
126 }
else if(invoke ==
nullptr) {
127 find_member_or_assert()->custom = std::move(node);
129 find_overload_or_assert()->custom = std::move(node);
134 basic_meta_factory(meta_ctx &area, meta_type_node node)
136 parent{node.info->hash()},
138 if(
auto *curr = meta_context::from(*ctx).value.try_emplace(parent, std::make_unique<meta_type_node>(std::move(node))).first->second.get(); curr->details ==
nullptr) {
139 curr->details = std::make_unique<meta_type_descriptor>();
157template<
typename Type>
159 using base_type = internal::basic_meta_factory;
174 : internal::basic_meta_factory{area, internal::setup_node_for<Type>()} {}
192 base_type::type(
id, name);
204 template<
typename Base>
206 static_assert(!std::is_same_v<Type, Base> && std::is_base_of_v<Base, Type>,
"Invalid base type");
207 auto *
const op = +[](
const void *instance)
noexcept {
return static_cast<const void *
>(
static_cast<const Base *
>(
static_cast<const Type *
>(instance))); };
208 base_type::insert_or_assign(internal::meta_base_node{
type_id<Base>().
hash(), &internal::resolve<Base>, op});
224 template<auto Cand
idate>
226 using conv_type = std::remove_const_t<std::remove_reference_t<std::invoke_result_t<
decltype(Candidate), Type &>>>;
227 auto *
const op = +[](
const meta_ctx &area,
const void *instance) {
return forward_as_meta(area, std::invoke(Candidate, *
static_cast<const Type *
>(instance))); };
241 template<
typename To>
243 using conv_type = std::remove_const_t<std::remove_reference_t<To>>;
244 auto *
const op = +[](
const meta_ctx &area,
const void *instance) {
return forward_as_meta(area,
static_cast<To
>(*
static_cast<const Type *
>(instance))); };
262 template<auto Cand
idate,
typename Policy = as_value_t>
265 static_assert(Policy::template value<typename descriptor::return_type>,
"Invalid return type for the given policy");
266 static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<typename descriptor::return_type>>, Type>,
"The function doesn't return an object of the required type");
281 template<
typename... Args>
284 if constexpr(
sizeof...(Args) != 0u) {
299 template<auto Data,
typename Policy = as_value_t>
318 template<auto Data,
typename Policy = as_value_t>
320 if constexpr(std::is_member_object_pointer_v<
decltype(Data)>) {
321 using data_type = std::invoke_result_t<
decltype(Data), Type &>;
322 static_assert(Policy::template value<data_type>,
"Invalid return type for the given policy");
325 internal::meta_data_node{
329 std::is_const_v<std::remove_reference_t<data_type>> ? internal::meta_traits::is_const : internal::meta_traits::is_none,
331 &internal::resolve<std::remove_const_t<std::remove_reference_t<data_type>>>,
336 using data_type = std::remove_pointer_t<
decltype(Data)>;
338 if constexpr(std::is_pointer_v<
decltype(Data)>) {
339 static_assert(Policy::template value<
decltype(*Data)>,
"Invalid return type for the given policy");
341 static_assert(Policy::template value<data_type>,
"Invalid return type for the given policy");
345 internal::meta_data_node{
348 ((!std::is_pointer_v<
decltype(Data)> || std::is_const_v<data_type>) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static,
350 &internal::resolve<std::remove_const_t<std::remove_reference_t<data_type>>>,
368 template<auto Setter, auto Getter,
typename Policy = as_value_t>
394 template<auto Setter, auto Getter,
typename Policy = as_value_t>
397 static_assert(Policy::template value<typename descriptor::return_type>,
"Invalid return type for the given policy");
399 if constexpr(std::is_same_v<
decltype(Setter), std::nullptr_t>) {
401 internal::meta_data_node{
405 internal::meta_traits::is_const,
407 &internal::resolve<std::remove_const_t<std::remove_reference_t<typename descriptor::return_type>>>,
415 internal::meta_data_node{
419 internal::meta_traits::is_none,
421 &internal::resolve<std::remove_const_t<std::remove_reference_t<typename descriptor::return_type>>>,
437 template<auto Cand
idate,
typename Policy = as_value_t>
456 template<auto Cand
idate,
typename Policy = as_value_t>
459 static_assert(Policy::template value<typename descriptor::return_type>,
"Invalid return type for the given policy");
462 internal::meta_func_node{
465 (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),
466 descriptor::args_type::size,
467 &internal::resolve<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, std::remove_const_t<std::remove_reference_t<typename descriptor::return_type>>>>,
484 template<
typename Value>
486 static_assert(std::is_enum_v<Value>,
"Invalid enum type");
487 base_type::traits(internal::user_to_meta_traits(value), unset);
498 template<
typename Value,
typename... Args>
500 base_type::custom(internal::meta_custom_node{
type_id<Value>().
hash(), std::make_shared<Value>(std::forward<Args>(args)...)});
518 auto &context = internal::meta_context::from(ctx);
520 for(
auto it = context.value.begin(); it != context.value.end();) {
521 if(it->second->id ==
id) {
522 it = context.value.erase(it);
552template<
typename Type>
554 internal::meta_context::from(ctx).value.erase(
type_id<Type>().hash());
564template<
typename Type>
577 internal::meta_context::from(ctx).value.clear();
static constexpr hash_type value(const value_type *str, const size_type len) noexcept
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.
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::uint32_t id_type
Alias declaration for type identifiers.
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.
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.
void invoke(Registry ®, const typename Registry::entity_type entt)
Helper to create a listener that directly invokes a member function.
constexpr auto overload(Type Class::*member) noexcept
Constant utility to disambiguate overloaded members of a class.
meta_type meta_arg(const meta_ctx &ctx, const std::size_t index) noexcept
Returns the meta type of the i-th element of a list of arguments.
meta_type resolve(const meta_ctx &ctx) noexcept
Returns the meta type associated with a given type.
const type_info & type_id() noexcept
Returns the type info object associated to a given type.
@ ref
Aliasing mode, non-const reference.
constexpr id_type hash() const noexcept
Type hash.
A class to use to push around lists of types, nothing more.