1#ifndef ENTT_META_META_HPP
2#define ENTT_META_META_HPP
4#include "../config/config.h"
5#include "../core/any.hpp"
6#include "../core/concepts.hpp"
7#include "../core/fwd.hpp"
8#include "../core/iterator.hpp"
9#include "../core/type_info.hpp"
10#include "../core/type_traits.hpp"
11#include "../core/utility.hpp"
12#include "../locator/locator.hpp"
13#include "../stl/array.hpp"
14#include "../stl/concepts.hpp"
15#include "../stl/cstddef.hpp"
16#include "../stl/iterator.hpp"
17#include "../stl/memory.hpp"
18#include "../stl/string_view.hpp"
19#include "../stl/type_traits.hpp"
20#include "../stl/utility.hpp"
21#include "adl_pointer.hpp"
26#include "type_traits.hpp"
33template<
typename Type>
34struct basic_meta_object {
35 [[nodiscard]]
auto &node_or_assert() const noexcept {
36 ENTT_ASSERT(node !=
nullptr,
"Invalid pointer to node");
41 const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
66 template<
typename Type>
70 value_type_node{&internal::resolve<typename Type::value_type>},
71 const_reference_node{&internal::resolve<stl::remove_cvref_t<typename Type::const_reference>>},
72 size_fn{meta_sequence_container_traits<stl::remove_const_t<Type>>
::size},
73 clear_fn{meta_sequence_container_traits<stl::remove_const_t<Type>>
::clear},
74 reserve_fn{meta_sequence_container_traits<stl::remove_const_t<Type>>
::reserve},
75 resize_fn{meta_sequence_container_traits<stl::remove_const_t<Type>>
::resize},
76 begin_end_fn{meta_sequence_container_traits<stl::remove_const_t<Type>>::iter},
77 insert_fn{meta_sequence_container_traits<stl::remove_const_t<Type>>
::insert},
78 erase_fn{meta_sequence_container_traits<stl::remove_const_t<Type>>
::erase},
79 const_only{stl::is_const_v<Type>} {}
81 [[nodiscard]]
inline meta_type
value_type() const noexcept;
90 [[nodiscard]] inline meta_any operator[](
size_type);
91 [[nodiscard]] inline explicit operator
bool() const noexcept;
94 const meta_ctx *ctx{};
96 const internal::meta_type_node &(*value_type_node)(
const internal::meta_context &){};
97 const internal::meta_type_node &(*const_reference_node)(
const internal::meta_context &){};
99 bool (*clear_fn)(
void *){};
100 bool (*reserve_fn)(
void *,
const size_type){};
101 bool (*resize_fn)(
void *,
const size_type){};
102 iterator (*begin_end_fn)(
const meta_ctx &,
void *,
const void *,
const bool){};
103 iterator (*insert_fn)(
const meta_ctx &,
void *,
const void *,
const void *,
const iterator &){};
127 template<
typename Type>
131 key_type_node{&internal::resolve<typename Type::key_type>},
132 value_type_node{&internal::resolve<typename Type::value_type>},
133 size_fn{&meta_associative_container_traits<stl::remove_const_t<Type>>
::size},
134 clear_fn{&meta_associative_container_traits<stl::remove_const_t<Type>>
::clear},
135 reserve_fn{&meta_associative_container_traits<stl::remove_const_t<Type>>
::reserve},
136 begin_end_fn{&meta_associative_container_traits<stl::remove_const_t<Type>>::iter},
137 insert_fn{&meta_associative_container_traits<stl::remove_const_t<Type>>
::insert},
138 erase_fn{&meta_associative_container_traits<stl::remove_const_t<Type>>
::erase},
139 find_fn{&meta_associative_container_traits<stl::remove_const_t<Type>>
::find},
140 const_only{stl::is_const_v<Type>} {
141 if constexpr(!meta_associative_container_traits<stl::remove_const_t<Type>>::key_only) {
142 mapped_type_node = &internal::resolve<typename Type::mapped_type>;
146 [[nodiscard]]
inline meta_type
key_type() const noexcept;
147 [[nodiscard]] inline meta_type
mapped_type() const noexcept;
148 [[nodiscard]] inline meta_type
value_type() const noexcept;
154 inline
bool insert(meta_any, meta_any);
157 [[nodiscard]] inline explicit operator
bool() const noexcept;
160 const meta_ctx *ctx{};
162 const internal::meta_type_node &(*key_type_node)(
const internal::meta_context &){};
163 const internal::meta_type_node &(*mapped_type_node)(
const internal::meta_context &){};
164 const internal::meta_type_node &(*value_type_node)(
const internal::meta_context &){};
166 bool (*clear_fn)(
void *){};
167 bool (*reserve_fn)(
void *,
const size_type){};
168 iterator (*begin_end_fn)(
const meta_ctx &,
void *,
const void *,
const bool){};
169 bool (*insert_fn)(
void *,
const void *,
const void *){};
170 size_type (*erase_fn)(
void *,
const void *){};
171 iterator (*find_fn)(
const meta_ctx &,
void *,
const void *,
const void *){};
177 using vtable_type = void(
const internal::meta_traits,
const meta_any &,
void *);
179 template<cvref_unqualified Type>
180 static void basic_vtable(
const internal::meta_traits req,
const meta_any &value, [[maybe_unused]]
void *other) {
181 if(req == internal::meta_traits::is_none) {
182 value.node = &internal::resolve<Type>(internal::meta_context::from(*value.ctx));
186 if(req == internal::meta_traits::is_pointer) {
187 if constexpr(!stl::is_void_v<stl::remove_const_t<typename stl::pointer_traits<Type>::element_type>>) {
188 if constexpr(stl::is_constructible_v<bool, Type>) {
197 }
else if constexpr(
requires(Type elem) { *elem; }) {
198 if(req == internal::meta_traits::is_pointer) {
199 if constexpr(stl::is_class_v<Type>) {
201 return (value.storage.
policy() ==
any_policy::cref) ?
static_cast<meta_any *
>(other)->
emplace<
decltype(*elem)>(*elem) :
static_cast<meta_any *
>(other)->
emplace<
decltype(*
const_cast<Type &
>(elem))>(*
const_cast<Type &
>(elem));
203 }
else if constexpr(!stl::is_array_v<Type> && !stl::is_void_v<stl::remove_const_t<stl::remove_pointer_t<Type>>>) {
205 static_cast<meta_any *
>(other)->
emplace<stl::conditional_t<stl::is_function_v<stl::remove_const_t<stl::remove_pointer_t<Type>>>, Type, stl::remove_pointer_t<Type> &>>(*pointer);
217 [[nodiscard]]
const auto &fetch_node()
const {
218 if(node ==
nullptr) {
219 ENTT_ASSERT(*
this,
"Invalid vtable function");
220 vtable(internal::meta_traits::is_none, *
this,
nullptr);
223 ENTT_ASSERT(node !=
nullptr,
"Invalid pointer to node");
228 : storage{stl::move(elem)},
231 vtable{other.vtable} {}
249 template<
typename Type>
250 explicit meta_any(stl::in_place_type_t<Type>,
auto &&...args)
251 : meta_any{
locator<
meta_ctx>::value_or(),
stl::in_place_type<Type>,
stl::forward<decltype(args)>(args)...} {}
259 template<
typename Type>
261 : storage{
stl::in_place_type<Type>,
stl::forward<decltype(args)>(args)...},
263 vtable{&basic_vtable<
stl::remove_cvref_t<Type>>} {}
280 vtable{storage ? &basic_vtable<
stl::remove_const_t<
stl::remove_pointer_t<decltype(value)>>> : nullptr} {
288 requires (!stl::same_as<stl::remove_cvref_t<
decltype(value)>, meta_any>)
297 requires (!stl::same_as<stl::remove_cvref_t<
decltype(value)>, meta_any>)
298 : meta_any{area,
stl::in_place_type<
stl::remove_cvref_t<decltype(value)>>,
stl::forward<decltype(value)>(value)} {}
306 : storage{other.storage},
308 node{(ctx == other.ctx) ? other.node : nullptr},
309 vtable{other.vtable} {}
317 : storage{
stl::move(other.storage)},
319 node{(ctx == other.ctx) ?
stl::exchange(other.node, nullptr) : nullptr},
320 vtable{
stl::exchange(other.vtable, nullptr)} {}
327 : storage{other.storage},
329 node{(other.storage && !storage) ? nullptr : other.node},
330 vtable{(other.storage && !storage) ? nullptr : other.vtable} {
338 : storage{stl::move(other.storage)},
340 node{stl::exchange(other.node,
nullptr)},
341 vtable{stl::exchange(other.vtable,
nullptr)} {}
354 storage = other.storage;
355 node = (other.storage && !storage) ?
nullptr : other.node;
356 vtable = (other.storage && !storage) ?
nullptr : other.vtable;
368 storage = stl::move(other.storage);
370 node = stl::exchange(other.node,
nullptr);
371 vtable = stl::exchange(other.vtable,
nullptr);
381 requires (!stl::same_as<stl::remove_cvref_t<
decltype(value)>, meta_any>) {
382 emplace<stl::remove_cvref_t<
decltype(value)>>(stl::forward<
decltype(value)>(value));
433 template<typename Type>
436 return ((elem !=
nullptr) || !*
this) ? elem :
static_cast<const Type *
>(internal::try_cast(internal::meta_context::from(*ctx), fetch_node(),
type_hash<stl::remove_const_t<Type>>::value(), storage.data()));
440 template<
typename Type>
442 return ((storage.policy() ==
any_policy::cref) && !stl::is_const_v<Type>) ? nullptr :
const_cast<Type *
>(stl::as_const(*this).try_cast<stl::remove_const_t<Type>>());
450 template<
typename Type>
451 [[nodiscard]] stl::remove_const_t<Type>
cast()
const {
453 ENTT_ASSERT(instance,
"Invalid instance");
454 return static_cast<Type
>(*instance);
458 template<
typename Type>
459 [[nodiscard]] stl::remove_const_t<Type>
cast() {
462 ENTT_ASSERT(instance,
"Invalid instance");
463 return static_cast<Type
>(*instance);
485 template<
typename Type>
487 if constexpr(!stl::is_reference_v<Type> || stl::is_const_v<stl::remove_reference_t<Type>>) {
488 if(storage.has_value<stl::remove_cvref_t<Type>>()) {
491 if constexpr(stl::is_arithmetic_v<stl::remove_cvref_t<Type>> || stl::is_enum_v<stl::remove_cvref_t<Type>>) {
492 if(
const auto &from = fetch_node(); from.conversion_helper) {
493 return meta_any{*ctx,
static_cast<Type
>(from.conversion_helper(
nullptr, storage.data()))};
497 if(
const auto &from = fetch_node(); from.details !=
nullptr) {
498 if(
const auto *elem = internal::find_member(from.details->conv,
entt::type_hash<stl::remove_cvref_t<Type>>::value()); elem !=
nullptr) {
499 return elem->conv(*ctx, storage.data());
502 for(
auto &&curr: from.details->base) {
503 if(
auto other = curr.type(internal::meta_context::from(*ctx)).from_void(*ctx,
nullptr, curr.cast(storage.data())); curr.id ==
entt::type_hash<stl::remove_cvref_t<Type>>::value()) {
505 }
else if(
auto from_base = stl::as_const(other).
template allow_cast<Type>(); from_base) {
521 template<
typename Type>
523 if constexpr(stl::is_reference_v<Type> && !stl::is_const_v<stl::remove_reference_t<Type>>) {
526 if(storage.has_value<stl::remove_cvref_t<Type>>()) {
528 }
else if(
auto other = stl::as_const(*this).allow_cast<stl::remove_cvref_t<Type>>(); other) {
529 if(other.storage.owner()) {
530 stl::swap(*
this, other);
541 template<
typename Type>
543 storage.emplace<Type>(stl::forward<decltype(args)>(args)...);
544 auto *prev = stl::exchange(vtable, &basic_vtable<stl::remove_cvref_t<Type>>);
545 node = (prev == vtable) ? node :
nullptr;
567 if(*
this) { vtable(internal::meta_traits::is_sequence_container, *
this, &proxy); }
574 if(*
this) { vtable(internal::meta_traits::is_sequence_container,
as_ref(), &proxy); }
584 if(*
this) { vtable(internal::meta_traits::is_associative_container, *
this, &proxy); }
591 if(*
this) { vtable(internal::meta_traits::is_associative_container,
as_ref(), &proxy); }
602 if(*
this) { vtable(internal::meta_traits::is_pointer, *
this, &ret); }
609 if(*
this) { vtable(internal::meta_traits::is_pointer,
as_ref(), &ret); }
614 [[nodiscard]]
explicit operator bool() const noexcept {
615 return !(vtable ==
nullptr);
619 [[nodiscard]]
bool operator==(
const meta_any &other)
const noexcept {
620 return (ctx == other.ctx) && (!*
this == !other) && (storage == other.storage);
624 [[nodiscard]] meta_any
as_ref() noexcept {
625 return meta_any{*
this, storage.as_ref()};
629 [[nodiscard]] meta_any
as_ref() const noexcept {
630 return meta_any{*
this, storage.as_ref()};
637 [[nodiscard]]
const any &
base() const noexcept {
652 mutable const internal::meta_type_node *node{};
653 vtable_type *vtable{};
663 return meta_any{ctx, stl::in_place_type<
decltype(value)>, stl::forward<
decltype(value)>(value)};
678 requires stl::same_as<stl::remove_cvref_t<
decltype(value)>,
meta_any>
679 : any{stl::forward<decltype(args)>(args)..., value.as_ref()} {}
682 : any{stl::forward<decltype(args)>(args)..., stl::in_place_type<
decltype(value)>, value} {}
694 requires (!stl::same_as<stl::remove_cvref_t<
decltype(value)>, meta_handle>)
695 : meta_handle{0, value, ctx} {}
702 requires (!stl::same_as<stl::remove_cvref_t<
decltype(value)>, meta_handle>)
703 : meta_handle{0, value} {}
711 : any{area,
stl::move(other.any)} {}
738 [[nodiscard]]
explicit operator bool() const noexcept {
739 return static_cast<bool>(any);
770 template<
typename Type>
771 [[nodiscard]]
operator Type *()
const noexcept {
772 return ((node !=
nullptr) && (
type_hash<stl::remove_const_t<Type>>::value() == node->id)) ?
static_cast<Type *
>(node->value.get()) :
nullptr;
779 template<
typename Type>
780 [[nodiscard]]
operator Type &()
const noexcept {
781 ENTT_ASSERT(
static_cast<Type *
>(*
this) !=
nullptr,
"Invalid type");
782 return *
static_cast<Type *
>(node->value.get());
786 const internal::meta_custom_node *node{};
793template<
typename Type>
809 : internal::basic_meta_object<Type>{&curr, &area} {
816 [[nodiscard]]
explicit operator bool() const noexcept {
817 return (this->node !=
nullptr);
826 return (this->ctx == other.ctx) && (this->node == other.node);
838 [[nodiscard]] stl::string_view
name() const noexcept {
839 return (node_or_assert().
name ==
nullptr) ? stl::string_view{} : stl::string_view{node_or_assert().name};
847 return node_or_assert().set_arity;
855 return node_or_assert().get_arity;
863 return !!(node_or_assert().traits & internal::meta_traits::is_const);
871 return !!(node_or_assert().traits & internal::meta_traits::is_static);
886 bool set(Instance &&instance, auto &&...args)
const {
887 return (
sizeof...(args) >=
set_arity()) && node_or_assert().
set(
meta_handle{*ctx, stl::forward<Instance>(instance)}, stl::array<
meta_any,
sizeof...(args)>{
meta_any{*ctx, stl::forward<decltype(args)>(args)}...}.data());
897 template<
typename Instance = meta_handle>
898 [[nodiscard]]
meta_any get(Instance &&instance,
auto &&...args)
const {
921 template<
typename Type>
922 [[nodiscard]] Type
traits() const noexcept {
923 return internal::meta_to_user_traits<Type>(node_or_assert().
traits);
931 return {node_or_assert().custom};
943 [[nodiscard]] stl::string_view
name() const noexcept {
944 return (node_or_assert().
name ==
nullptr) ? stl::string_view{} : stl::string_view{node_or_assert().name};
952 return node_or_assert().arity;
960 return !!(node_or_assert().traits & internal::meta_traits::is_const);
968 return !!(node_or_assert().traits & internal::meta_traits::is_static);
998 template<
typename Type>
999 [[nodiscard]] Type
traits() const noexcept {
1000 return internal::meta_to_user_traits<Type>(node_or_assert().
traits);
1005 return {node_or_assert().custom};
1027 friend class meta_any;
1029 [[nodiscard]]
const auto &fetch_node()
const {
1030 return (node ==
nullptr) ? internal::resolve<void>(internal::meta_context::from(*ctx)) : *node;
1033 [[nodiscard]]
auto lookup(
meta_handle *
const args,
const auto sz, [[maybe_unused]]
bool constness,
auto next)
const {
1034 decltype(next()) candidate =
nullptr;
1038 for(
auto curr = next(); curr; curr = next()) {
1039 if constexpr(stl::is_same_v<stl::decay_t<
decltype(*curr)>, internal::meta_func_node>) {
1040 if(constness && !(curr->traits & internal::meta_traits::is_const)) {
1045 if(curr->arity == sz) {
1050 for(; pos < sz; ++pos) {
1051 const auto other = curr->arg(*ctx, pos);
1052 const auto type = args[pos]->
type();
1054 if(
const auto &
info = other.info();
info ==
type.info()) {
1056 }
else if(!(
type.fetch_node().conversion_helper && other.fetch_node().conversion_helper) && !(
type.fetch_node().details && (internal::find_member(
type.fetch_node().details->base,
info.hash()) || internal::find_member(
type.fetch_node().details->conv,
info.hash())))) {
1063 if(!candidate || match > same) {
1067 }
else if(match == same) {
1068 if constexpr(stl::is_same_v<stl::decay_t<
decltype(*curr)>, internal::meta_func_node>) {
1069 if(!!(curr->traits & internal::meta_traits::is_const) != !!(candidate->traits & internal::meta_traits::is_const)) {
1070 candidate = !!(candidate->traits & internal::meta_traits::is_const) ? curr : candidate;
1082 return ambiguous ? nullptr : candidate;
1106 return *fetch_node().info;
1114 return fetch_node().alias;
1121 [[nodiscard]] stl::string_view
name() const noexcept {
1122 return (fetch_node().
name ==
nullptr) ? stl::string_view{} : stl::string_view{fetch_node().name};
1130 return fetch_node().size_of;
1139 return !!(fetch_node().traits & internal::meta_traits::is_arithmetic);
1147 return !!(fetch_node().traits & internal::meta_traits::is_integral);
1155 return !!(fetch_node().traits & internal::meta_traits::is_signed);
1163 return !!(fetch_node().traits & internal::meta_traits::is_array);
1171 return !!(fetch_node().traits & internal::meta_traits::is_enum);
1179 return !!(fetch_node().traits & internal::meta_traits::is_class);
1187 return !!(fetch_node().traits & internal::meta_traits::is_pointer);
1196 return meta_type{*ctx, fetch_node().remove_pointer(internal::meta_context::from(*ctx))};
1204 return !!(fetch_node().traits & internal::meta_traits::is_pointer_like);
1212 return !!(fetch_node().traits & internal::meta_traits::is_sequence_container);
1220 return !!(fetch_node().traits & internal::meta_traits::is_associative_container);
1228 return (fetch_node().templ.arity != 0u);
1236 return fetch_node().templ.arity;
1244 return (fetch_node().templ.resolve !=
nullptr) ?
meta_type{*ctx, fetch_node().templ.resolve(internal::meta_context::from(*ctx))} :
meta_type{};
1263 return other && ((*
this == other) || (internal::try_cast(internal::meta_context::from(*ctx), fetch_node(), other.fetch_node().info->hash(),
this) !=
nullptr));
1272 if(
const auto &to = other.info().hash(); (
info().hash() == to) || ((fetch_node().conversion_helper !=
nullptr) && (other.is_arithmetic() || other.is_enum()))) {
1274 }
else if(
const auto &from = fetch_node(); from.details) {
1275 if(
const auto *elem = internal::find_member(from.details->conv, to); elem !=
nullptr) {
1279 for(
auto &&curr: from.details->base) {
1280 if(curr.id == to ||
meta_type{*ctx, curr.type(internal::meta_context::from(*ctx))}.can_convert(other)) {
1294 using range_type =
meta_range<
meta_base,
decltype(internal::meta_type_descriptor::base)::const_iterator>;
1295 return fetch_node().details ? range_type{{*ctx, fetch_node().details->base.cbegin()}, {*ctx, fetch_node().details->base.cend()}} : range_type{};
1303 using range_type =
meta_range<
meta_data,
decltype(internal::meta_type_descriptor::data)::const_iterator>;
1304 return fetch_node().details ? range_type{{*ctx, fetch_node().details->data.cbegin()}, {*ctx, fetch_node().details->data.cend()}} : range_type{};
1314 const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), fetch_node(),
id, recursive);
1323 using return_type =
meta_range<
meta_func,
decltype(internal::meta_type_descriptor::func)::const_iterator>;
1324 return fetch_node().details ? return_type{{*ctx, fetch_node().details->func.cbegin()}, {*ctx, fetch_node().details->func.cend()}} : return_type{};
1334 const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), fetch_node(),
id, recursive);
1344 if(
const auto &
ref = fetch_node();
ref.details) {
1345 if(
const auto *candidate = lookup(stl::array<
meta_handle,
sizeof...(args)>{
meta_handle{*ctx, args}...}.data(),
sizeof...(args),
false, [first =
ref.details->ctor.cbegin(), last =
ref.details->ctor.cend()]()
mutable { return first == last ? nullptr : &*(first++); }); candidate) {
1346 return candidate->invoke(*ctx, stl::array<meta_any,
sizeof...(args)>{meta_any{*ctx, stl::forward<decltype(args)>(args)}...}.data());
1350 if(
const auto &
ref = fetch_node(); (
sizeof...(args) == 0u) && (
ref.default_constructor !=
nullptr)) {
1351 return ref.default_constructor(*ctx);
1363 [[nodiscard]] meta_any
from_void(
void *elem,
bool transfer_ownership =
false)
const {
1364 return ((elem !=
nullptr) && (fetch_node().
from_void !=
nullptr)) ? fetch_node().from_void(*ctx, elem, transfer_ownership ? elem :
nullptr) : meta_any{
meta_ctx_arg, *ctx};
1373 return ((elem !=
nullptr) && (fetch_node().
from_void !=
nullptr)) ? fetch_node().from_void(*ctx,
nullptr, elem) : meta_any{
meta_ctx_arg, *ctx};
1384 template<
typename Instance = meta_handle>
1387 meta_handle wrapped{*ctx, stl::forward<Instance>(instance)};
1389 if(
const auto &
ref = fetch_node();
ref.details) {
1390 if(
auto *elem = internal::find_member(
ref.details->func,
id); elem !=
nullptr) {
1391 if(
const auto *candidate = lookup(stl::array<
meta_handle,
sizeof...(args)>{
meta_handle{*ctx, args}...}.data(),
sizeof...(args), (wrapped->
base().
policy() ==
any_policy::cref), [curr = elem]()
mutable { return (curr != nullptr) ? stl::exchange(curr, curr->next.get()) : nullptr; }); candidate) {
1392 return candidate->invoke(stl::move(wrapped), stl::array<meta_any,
sizeof...(args)>{meta_any{*ctx, stl::forward<decltype(args)>(args)}...}.data());
1397 for(
auto &&curr:
base()) {
1398 if(
auto elem = curr.second.type().invoke(
id, *wrapped.operator->(), stl::forward<
decltype(args)>(args)...); elem) {
1414 template<
typename Instance = meta_handle>
1416 bool set(
const id_type id, Instance &&instance,
auto &&...args)
const {
1417 const auto candidate =
data(
id);
1418 return candidate && candidate.set(stl::forward<Instance>(instance), stl::forward<
decltype(args)>(args)...);
1429 template<
typename Instance = meta_handle>
1430 [[nodiscard]] meta_any
get(
const id_type id, Instance &&instance,
auto &&...args)
const {
1431 const auto candidate =
data(
id);
1432 return candidate ? candidate.get(stl::forward<Instance>(instance), stl::forward<
decltype(args)>(args)...) : meta_any{
meta_ctx_arg, *ctx};
1436 template<
typename Type>
1438 return internal::meta_to_user_traits<Type>(fetch_node().
traits);
1443 return fetch_node().custom;
1447 [[nodiscard]]
explicit operator bool() const noexcept {
1448 return (node !=
nullptr);
1453 return (ctx == other.ctx) && (fetch_node().alias == other.fetch_node().alias);
1457 mutable const internal::meta_type_node *node{};
1466 ENTT_ASSERT(storage.info() == alias.info(),
"Unexpected type");
1473 return type().
invoke(
id, *
this, stl::forward<
decltype(args)>(args)...);
1477 return type().
invoke(
id, *
this, stl::forward<
decltype(args)>(args)...);
1481 return type().
set(
id, *
this, stl::forward<
decltype(args)>(args)...);
1485 return type().
get(
id, *
this, stl::forward<
decltype(args)>(args)...);
1489 return type().
get(
id, *
this, stl::forward<
decltype(args)>(args)...);
1493 if(storage.has_value(
type.info())) {
1496 if(
const auto &from = fetch_node(); (from.conversion_helper !=
nullptr) && (
type.is_arithmetic() ||
type.is_enum())) {
1497 auto other =
type.construct();
1498 const auto value = from.conversion_helper(
nullptr, storage.data());
1499 other.fetch_node().conversion_helper(other.storage.data(), &value);
1503 if(
const auto &from = fetch_node(); from.details) {
1504 if(
const auto *elem = internal::find_member(from.details->conv,
type.info().hash()); elem !=
nullptr) {
1505 return elem->conv(*ctx, storage.data());
1508 for(
auto &&curr: from.details->base) {
1509 if(
auto other = curr.type(internal::meta_context::from(*ctx)).from_void(*ctx,
nullptr, curr.cast(storage.data())); curr.id ==
type.info().hash()) {
1511 }
else if(
auto from_base = stl::as_const(other).
allow_cast(
type); from_base) {
1522 if(storage.has_value(
type.info())) {
1524 }
else if(
auto other = stl::as_const(*this).allow_cast(
type); other) {
1525 if(other.storage.owner()) {
1526 stl::swap(*
this, other);
1536 if(!storage.assign(other.storage)) {
1538 return storage.
assign(value.storage);
1545 return storage.
assign(stl::move(other.storage)) || storage.assign(stl::as_const(other).
allow_cast(
type()).storage);
1549 return meta_type{*ctx, node_or_assert().type(internal::meta_context::from(*ctx))};
1561 return meta_type{*ctx, node_or_assert().ret(internal::meta_context::from(*ctx))};
1565 return index <
arity() ? node_or_assert().arg(*ctx, index) :
meta_type{};
1569 return meta_type{*ctx, node_or_assert().type(internal::meta_context::from(*ctx))};
1573class meta_sequence_container::meta_iterator final {
1574 using vtable_type = void(
const void *,
const stl::ptrdiff_t,
meta_any *);
1576 template<
typename It>
1577 static void basic_vtable(
const void *value,
const stl::ptrdiff_t offset,
meta_any *other) {
1578 const auto &it = *
static_cast<const It *
>(value);
1579 other ? other->
emplace<
decltype(*it)>(*it) : stl::advance(
const_cast<It &
>(it), offset);
1583 using value_type = meta_any;
1584 using pointer = input_iterator_pointer<value_type>;
1585 using reference = value_type;
1586 using difference_type = stl::ptrdiff_t;
1587 using iterator_category = stl::input_iterator_tag;
1588 using iterator_concept = stl::bidirectional_iterator_tag;
1590 meta_iterator() =
default;
1592 meta_iterator(
const meta_ctx &area, stl::bidirectional_iterator
auto iter) noexcept
1594 vtable{&basic_vtable<
decltype(iter)>},
1597 meta_iterator &operator++() noexcept {
1598 return vtable(
handle.data(), 1,
nullptr), *
this;
1601 meta_iterator operator++(
int value)
noexcept {
1602 meta_iterator orig = *
this;
1603 vtable(
handle.data(), ++value,
nullptr);
1607 meta_iterator &operator--() noexcept {
1608 return vtable(
handle.data(), -1,
nullptr), *
this;
1611 meta_iterator operator--(
int value)
noexcept {
1612 meta_iterator orig = *
this;
1613 vtable(
handle.data(), --value,
nullptr);
1617 [[nodiscard]] reference operator*()
const {
1619 vtable(
handle.data(), 0, &other);
1623 [[nodiscard]] pointer operator->()
const {
1627 [[nodiscard]]
explicit operator bool() const noexcept {
1628 return (vtable !=
nullptr);
1631 [[nodiscard]]
bool operator==(
const meta_iterator &other)
const noexcept {
1632 return handle == other.handle;
1635 [[nodiscard]]
const any &base() const noexcept {
1640 const meta_ctx *ctx{};
1641 vtable_type *vtable{};
1645class meta_associative_container::meta_iterator final {
1646 using vtable_type = void(
const void *, stl::pair<meta_any, meta_any> *);
1648 template<
bool KeyOnly,
typename It>
1649 static void basic_vtable(
const void *value, stl::pair<meta_any, meta_any> *other) {
1650 if(
const auto &it = *
static_cast<const It *
>(value); other) {
1651 if constexpr(KeyOnly) {
1652 other->first.emplace<
decltype(*it)>(*it);
1654 other->first.emplace<
decltype((it->first))>(it->first);
1655 other->second.emplace<
decltype((it->second))>(it->second);
1658 ++
const_cast<It &
>(it);
1663 using value_type = stl::pair<meta_any, meta_any>;
1664 using pointer = input_iterator_pointer<value_type>;
1665 using reference = value_type;
1666 using difference_type = stl::ptrdiff_t;
1667 using iterator_category = stl::input_iterator_tag;
1668 using iterator_concept = stl::forward_iterator_tag;
1670 meta_iterator() =
default;
1672 template<
bool KeyOnly>
1673 meta_iterator(
const meta_ctx &area, stl::bool_constant<KeyOnly>, stl::forward_iterator
auto iter) noexcept
1675 vtable{&basic_vtable<KeyOnly,
decltype(iter)>},
1678 meta_iterator &operator++() noexcept {
1679 return vtable(
handle.data(),
nullptr), *
this;
1682 meta_iterator operator++(
int)
noexcept {
1683 meta_iterator orig = *
this;
1684 vtable(
handle.data(),
nullptr);
1688 [[nodiscard]] reference operator*()
const {
1690 vtable(
handle.data(), &other);
1694 [[nodiscard]] pointer operator->()
const {
1698 [[nodiscard]]
explicit operator bool() const noexcept {
1699 return (vtable !=
nullptr);
1702 [[nodiscard]]
bool operator==(
const meta_iterator &other)
const noexcept {
1703 return handle == other.handle;
1707 const meta_ctx *ctx{};
1708 vtable_type *vtable{};
1719 return (value_type_node !=
nullptr) ?
meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} :
meta_type{};
1727 return size_fn(data);
1736 return !const_only && resize_fn(
const_cast<void *
>(data), sz);
1744 return !const_only && clear_fn(
const_cast<void *
>(data));
1753 return !const_only && reserve_fn(
const_cast<void *
>(data), sz);
1761 return begin_end_fn(*ctx, const_only ?
nullptr :
const_cast<void *
>(data), data,
false);
1769 return begin_end_fn(*ctx, const_only ?
nullptr :
const_cast<void *
>(data), data,
true);
1780 if(
const auto &vtype = value_type_node(internal::meta_context::from(*ctx)); !const_only && (value.
allow_cast({*ctx, vtype}) || value.
allow_cast({*ctx, const_reference_node(internal::meta_context::from(*ctx))}))) {
1781 const bool is_value_type = (value.
type().info() == *vtype.
info);
1782 return insert_fn(*ctx,
const_cast<void *
>(data), is_value_type ? value.
base().
data() :
nullptr, is_value_type ?
nullptr : value.
base().
data(), it);
1794 return const_only ?
iterator{} : erase_fn(*ctx,
const_cast<void *
>(data), it);
1804 it.operator++(
static_cast<int>(pos) - 1);
1812[[nodiscard]]
inline meta_sequence_container::operator bool() const noexcept {
1813 return (data !=
nullptr);
1821 return (key_type_node !=
nullptr) ?
meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))} :
meta_type{};
1829 return (mapped_type_node !=
nullptr) ?
meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))} :
meta_type{};
1834 return (value_type_node !=
nullptr) ?
meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} :
meta_type{};
1839 return size_fn(data);
1844 return !const_only && clear_fn(
const_cast<void *
>(data));
1849 return !const_only && reserve_fn(
const_cast<void *
>(data), sz);
1854 return begin_end_fn(*ctx, const_only ?
nullptr :
const_cast<void *
>(data), data,
false);
1859 return begin_end_fn(*ctx, const_only ?
nullptr :
const_cast<void *
>(data), data,
true);
1869 return !const_only && key.
allow_cast(
meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})
1870 && ((mapped_type_node ==
nullptr) || value.allow_cast(meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))}))
1871 && insert_fn(
const_cast<void *
>(data), key.
base().
data(), value.base().data());
1880 return (!const_only && key.
allow_cast(
meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})) ? erase_fn(
const_cast<void *
>(data), key.
base().
data()) : 0u;
1889 return key.
allow_cast(
meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))}) ? find_fn(*ctx, const_only ?
nullptr :
const_cast<void *
>(data), data, key.
base().
data()) :
iterator{};
1896[[nodiscard]]
inline meta_associative_container::operator bool() const noexcept {
1897 return (data !=
nullptr);
const void * data() const noexcept
Returns an opaque pointer to the contained instance.
any_policy policy() const noexcept
Returns the current mode of an any object.
Service locator, nothing more.
static Service & value_or(Args &&...args)
Returns a service if available or sets it from a fallback type.
Custom EnTT namespace for the standard template library.
@ in_place
In-place deletion policy.
basic_handle< registry > handle
Alias declaration for the most common use case.
basic_any<> any
Alias declaration for the most common use case.
iterable_adaptor< internal::meta_range_iterator< Type, It > > meta_range
Iterable range to use to iterate all types of meta objects.
meta_any forward_as_meta(const meta_ctx &ctx, auto &&value)
Forwards its argument and avoids copies for lvalue references.
constexpr bool is_complete_v
Helper variable template.
constexpr get_t< Type... > get
Variable template for lists of observed elements.
constexpr meta_ctx_arg_t meta_ctx_arg
Constant of type meta_context_arg_t used to disambiguate calls.
constexpr auto is_meta_pointer_like_v
Helper variable template.
stl::remove_const_t< Type > any_cast(const basic_any< Len, Align > &data) noexcept
Performs type-safe access to the contained object.
void invoke(Registry ®, const typename Registry::entity_type entt)
Helper to create a listener that directly invokes a member function.
@ ref
Aliasing mode, non-const reference.
@ cref
Const aliasing mode, const reference.
stl::uint32_t id_type
Alias declaration for type identifiers.
basic_storage< Type > storage
Alias declaration for the most common use case.
Implementation specific information about a type.