1#ifndef ENTT_META_FACTORY_HPP
2#define ENTT_META_FACTORY_HPP
4#include "../config/config.h"
5#include "../core/bit.hpp"
6#include "../core/fwd.hpp"
7#include "../core/hashed_string.hpp"
8#include "../core/type_info.hpp"
9#include "../core/type_traits.hpp"
10#include "../locator/locator.hpp"
11#include "../stl/algorithm.hpp"
12#include "../stl/concepts.hpp"
13#include "../stl/cstddef.hpp"
14#include "../stl/cstdint.hpp"
15#include "../stl/functional.hpp"
16#include "../stl/memory.hpp"
17#include "../stl/type_traits.hpp"
18#include "../stl/utility.hpp"
32class basic_meta_factory {
33 using invoke_type = stl::remove_pointer_t<
decltype(meta_func_node::invoke)>;
41 [[nodiscard]]
auto *find_member_or_assert() {
42 auto *member = find_member(parent->details->data, bucket);
43 ENTT_ASSERT(member !=
nullptr,
"Cannot find member");
47 [[nodiscard]]
auto *find_overload_or_assert() {
48 ENTT_ASSERT(invoke !=
nullptr,
"Invoke function not available");
49 auto *
overload = find_overload(find_member(parent->details->func, bucket), invoke);
50 ENTT_ASSERT(overload !=
nullptr,
"Cannot find overload");
54 bool unique_alias(
const id_type alias)
const noexcept {
55 return (ctx->bucket.find(alias) == ctx->bucket.cend()) && (stl::find_if(ctx->bucket.cbegin(), ctx->bucket.cend(), [alias](
const auto &value) { return value.second->alias == alias; }) == ctx->bucket.cend());
59 void type(
const id_type alias,
const char *name)
noexcept {
61 ENTT_ASSERT((parent->alias == alias) || unique_alias(alias),
"Duplicate identifier");
62 parent->alias = alias;
66 template<
typename Type>
67 void insert_or_assign(Type node) {
70 if constexpr(stl::is_same_v<Type, meta_base_node>) {
71 auto *member = find_member(parent->details->base, node.id);
72 member ? (*member = node) : parent->details->base.emplace_back(node);
73 }
else if constexpr(stl::is_same_v<Type, meta_conv_node>) {
74 auto *member = find_member(parent->details->conv, node.id);
75 member ? (*member = node) : parent->details->conv.emplace_back(node);
77 static_assert(stl::is_same_v<Type, meta_ctor_node>,
"Unexpected type");
78 auto *member = find_member(parent->details->ctor, node.id);
79 member ? (*member = node) : parent->details->ctor.emplace_back(node);
83 void data(meta_data_node node) {
87 if(
auto *member = find_member(parent->details->data, node.id); member ==
nullptr) {
88 parent->details->data.emplace_back(stl::move(node));
89 }
else if(member->set != node.set || member->get != node.get) {
90 *member = stl::move(node);
94 void func(meta_func_node node) {
99 if(
auto *member = find_member(parent->details->func, node.id); member ==
nullptr) {
100 parent->details->func.emplace_back(stl::move(node));
101 }
else if(
auto *overload = find_overload(member, node.invoke); overload ==
nullptr) {
102 while(member->next !=
nullptr) { member = member->next.get(); }
103 member->next = stl::make_unique<meta_func_node>(stl::move(node));
107 void traits(
const meta_traits value,
const bool unset) {
108 const auto set_or_unset_on = [=](
auto &node) {
109 node.traits = (unset ? (node.traits & ~value) : (node.traits | value));
114 set_or_unset_on(*parent);
117 set_or_unset_on(*find_member_or_assert());
120 set_or_unset_on(*find_overload_or_assert());
125 void custom(meta_custom_node node) {
128 parent->custom = stl::move(node);
131 find_member_or_assert()->custom = stl::move(node);
134 find_overload_or_assert()->custom = stl::move(node);
140 basic_meta_factory(meta_ctx &area, meta_type_node node,
const id_type
id)
141 : ctx{&meta_context::from(area)},
144 if(
const auto it = ctx->bucket.find(
id); it == ctx->bucket.cend()) {
145 ENTT_ASSERT(unique_alias(id),
"Duplicate identifier");
146 parent = ctx->bucket.emplace(id, stl::make_unique<meta_type_node>(stl::move(node))).first->second.get();
147 parent->details = stl::make_unique<meta_type_descriptor>();
150 parent = it->second.get();
157 meta_type_node *parent{};
169template<
typename Type>
171 using base_type = internal::basic_meta_factory;
201 : base_type{area, internal::setup_node_for<element_type>(),
id} {}
219 base_type::type(alias, name);
231 template<
typename Base>
232 requires stl::derived_from<element_type, Base>
234 if constexpr(!stl::same_as<element_type, Base>) {
235 auto *
const op = +[](
const void *instance)
noexcept {
return static_cast<const void *
>(
static_cast<const Base *
>(
static_cast<const element_type *
>(instance))); };
237 base_type::insert_or_assign(
238 internal::meta_base_node{
240 &internal::resolve<Base>,
259 template<auto Cand
idate>
261 using conv_type = stl::remove_cvref_t<stl::invoke_result_t<
decltype(Candidate),
element_type &>>;
264 base_type::insert_or_assign(
265 internal::meta_conv_node{
281 template<
typename To>
283 using conv_type = stl::remove_cvref_t<To>;
286 base_type::insert_or_assign(
287 internal::meta_conv_node{
307 template<auto Cand
idate,
typename Policy = as_value_t>
310 static_assert(Policy::template value<typename descriptor::return_type>,
"Invalid return type for the given policy");
311 static_assert(stl::is_same_v<stl::remove_cvref_t<typename descriptor::return_type>,
element_type>,
"The function doesn't return an object of the required type");
313 base_type::insert_or_assign(
314 internal::meta_ctor_node{
316 descriptor::args_type::size,
333 template<
typename... Args>
336 if constexpr(
sizeof...(Args) != 0u) {
339 base_type::insert_or_assign(
340 internal::meta_ctor_node{
342 descriptor::args_type::size,
357 template<auto Data,
typename Policy = as_value_t>
376 template<auto Data,
typename Policy = as_value_t>
378 if constexpr(stl::is_member_object_pointer_v<
decltype(Data)>) {
379 using data_type = stl::invoke_result_t<
decltype(Data),
element_type &>;
380 static_assert(Policy::template value<data_type>,
"Invalid return type for the given policy");
383 internal::meta_data_node{
387 stl::is_const_v<stl::remove_reference_t<data_type>> ? internal::meta_traits::is_const : internal::meta_traits::is_none,
392 &internal::resolve<stl::remove_cvref_t<data_type>>,
396 using data_type = stl::remove_pointer_t<
decltype(Data)>;
398 if constexpr(stl::is_pointer_v<
decltype(Data)>) {
399 static_assert(Policy::template value<
decltype(*Data)>,
"Invalid return type for the given policy");
401 static_assert(Policy::template value<data_type>,
"Invalid return type for the given policy");
405 internal::meta_data_node{
408 ((!stl::is_pointer_v<
decltype(Data)> || stl::is_const_v<data_type>) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static,
413 &internal::resolve<stl::remove_cvref_t<data_type>>,
430 template<auto Setter, auto Getter,
typename Policy = as_value_t>
456 template<auto Setter, auto Getter,
typename Policy = as_value_t>
459 static_assert(Policy::template value<typename getter::return_type>,
"Invalid return type for the given policy");
461 if constexpr(stl::is_same_v<
decltype(Setter), stl::nullptr_t>) {
463 internal::meta_data_node{
467 internal::meta_traits::is_const,
469 getter::args_type::size,
472 &internal::resolve<stl::remove_cvref_t<typename getter::return_type>>,
479 internal::meta_data_node{
483 internal::meta_traits::is_none,
484 setter::args_type::size,
485 getter::args_type::size,
488 &internal::resolve<stl::remove_cvref_t<typename getter::return_type>>,
503 template<auto Cand
idate,
typename Policy = as_value_t>
522 template<auto Cand
idate,
typename Policy = as_value_t>
525 static_assert(Policy::template value<typename descriptor::return_type>,
"Invalid return type for the given policy");
528 internal::meta_func_node{
531 (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),
532 descriptor::args_type::size,
533 &internal::resolve<stl::conditional_t<stl::is_same_v<Policy, as_void_t>, void, stl::remove_cvref_t<typename descriptor::return_type>>>,
550 template<
typename Value>
552 static_assert(stl::is_enum_v<Value>,
"Invalid enum type");
553 base_type::traits(internal::user_to_meta_traits(value), unset);
564 template<
typename Value,
typename... Args>
566 base_type::custom(internal::meta_custom_node{
type_id<Value>().
hash(), stl::make_shared<Value>(stl::forward<Args>(args)...)});
584 auto &bucket = internal::meta_context::from(ctx).bucket;
587 if(bucket.erase(alias) == 0u) {
588 if(
const auto it = stl::find_if(bucket.cbegin(), bucket.cend(), [alias](
const auto &value) { return value.second->alias == alias; }); it != bucket.cend()) {
617template<
typename Type>
619 internal::meta_context::from(ctx).bucket.erase(
type_id<Type>().hash());
629template<
typename Type>
642 internal::meta_context::from(ctx).bucket.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.
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 forward_as_meta(const meta_ctx &ctx, auto &&value)
Forwards its argument and avoids copies for lvalue references.
void meta_reset() noexcept
Resets a type and all its parts.
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 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.
const type_info & type_id() noexcept
Returns the type info object associated to a given type.
stl::uint32_t id_type
Alias declaration for type identifiers.
bool meta_setter(meta_handle instance, meta_any *const args)
Sets the value of a given variable.
static constexpr id_type value() noexcept
Returns the numeric representation of a given type.
constexpr id_type hash() const noexcept
Type hash.
A class to use to push around lists of types, nothing more.