1#ifndef ENTT_META_META_HPP
2#define ENTT_META_META_HPP
10#include "../config/config.h"
11#include "../core/any.hpp"
12#include "../core/fwd.hpp"
13#include "../core/iterator.hpp"
14#include "../core/type_info.hpp"
15#include "../core/type_traits.hpp"
16#include "../core/utility.hpp"
17#include "../locator/locator.hpp"
18#include "adl_pointer.hpp"
23#include "type_traits.hpp"
55 template<
typename Type>
56 void rebind(Type &instance)
noexcept {
57 value_type_node = &internal::resolve<typename Type::value_type>;
58 const_reference_node = &internal::resolve<std::remove_const_t<std::remove_reference_t<typename Type::const_reference>>>;
67 const_only = std::is_const_v<Type>;
81 [[nodiscard]] inline explicit operator
bool() const noexcept;
85 internal::meta_type_node (*value_type_node)(
const internal::meta_context &){};
86 internal::meta_type_node (*const_reference_node)(
const internal::meta_context &){};
88 bool (*clear_fn)(
void *){};
89 bool (*reserve_fn)(
void *,
const size_type){};
90 bool (*resize_fn)(
void *,
const size_type){};
91 iterator (*begin_fn)(
const meta_ctx &,
void *,
const void *){};
92 iterator (*end_fn)(
const meta_ctx &,
void *,
const void *){};
93 iterator (*insert_fn)(
const meta_ctx &,
void *,
const void *,
const void *,
const iterator &){};
124 template<
typename Type>
126 key_type_node = &internal::resolve<typename Type::key_type>;
127 value_type_node = &internal::resolve<typename Type::value_type>;
130 mapped_type_node = &internal::resolve<typename Type::mapped_type>;
141 const_only = std::is_const_v<Type>;
156 [[nodiscard]] inline explicit operator
bool() const noexcept;
160 internal::meta_type_node (*key_type_node)(
const internal::meta_context &){};
161 internal::meta_type_node (*mapped_type_node)(
const internal::meta_context &){};
162 internal::meta_type_node (*value_type_node)(
const internal::meta_context &){};
164 bool (*clear_fn)(
void *){};
165 bool (*reserve_fn)(
void *,
const size_type){};
166 iterator (*begin_fn)(
const meta_ctx &,
void *,
const void *){};
167 iterator (*end_fn)(
const meta_ctx &,
void *,
const void *){};
168 bool (*insert_fn)(
void *,
const void *,
const void *){};
169 size_type (*erase_fn)(
void *,
const void *){};
170 iterator (*find_fn)(
const meta_ctx &,
void *,
const void *,
const void *){};
180 using vtable_type = void(
const internal::meta_traits op,
const bool,
const void *,
void *);
182 template<
typename Type>
183 static std::enable_if_t<std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>> basic_vtable([[maybe_unused]]
const internal::meta_traits req, [[maybe_unused]]
const bool const_only, [[maybe_unused]]
const void *value, [[maybe_unused]]
void *other) {
185 if(req == internal::meta_traits::is_meta_pointer_like) {
186 if constexpr(std::is_function_v<typename std::pointer_traits<Type>::element_type>) {
188 }
else if constexpr(!std::is_void_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) {
191 if constexpr(std::is_constructible_v<bool, Type>) {
192 if(
const auto &pointer_like = *
static_cast<const Type *
>(value); pointer_like) {
203 if(req == internal::meta_traits::is_meta_sequence_container) {
209 if(req == internal::meta_traits::is_meta_associative_container) {
224 node{
storage ? other.node : internal::meta_type_node{}},
225 vtable{
storage ? other.vtable : &basic_vtable<void>} {}
244 template<
typename Type,
typename... Args>
245 explicit meta_any(std::in_place_type_t<Type>, Args &&...args)
255 template<
typename Type,
typename... Args>
257 :
storage{std::in_place_type<Type>, std::forward<Args>(args)...},
259 node{internal::
resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx))},
260 vtable{&basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>} {}
267 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
277 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
279 :
meta_any{area, std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
289 node{(other.node.
resolve != nullptr) ? other.node.
resolve(internal::meta_context::from(*ctx)) : other.node},
290 vtable{other.vtable} {}
300 node{(other.node.
resolve != nullptr) ? std::exchange(other.node, internal::meta_type_node{}).
resolve(internal::meta_context::from(*ctx)) : std::exchange(other.node, internal::meta_type_node{})},
301 vtable{std::exchange(other.vtable, &basic_vtable<void>)} {}
314 :
storage{std::move(other.storage)},
316 node{std::exchange(other.node, internal::meta_type_node{})},
317 vtable{std::exchange(other.vtable, &basic_vtable<void>)} {}
335 vtable = other.vtable;
347 ENTT_ASSERT(
this != &other,
"Self move assignment");
350 storage = std::move(other.storage);
352 node = std::exchange(other.node, internal::meta_type_node{});
353 vtable = std::exchange(other.vtable, &basic_vtable<void>);
363 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
373 [[nodiscard]] const
void *
data() const noexcept {
378 [[nodiscard]]
void *
data() noexcept {
389 template<
typename... Args>
393 template<
typename... Args>
403 template<
typename Type>
421 template<
typename Type>
423 const auto other = internal::resolve<std::remove_cv_t<Type>>(internal::meta_context::from(*ctx));
424 return static_cast<const Type *
>(internal::try_cast(internal::meta_context::from(*ctx), node, other,
data()));
428 template<
typename Type>
430 if constexpr(std::is_const_v<Type>) {
431 return std::as_const(*this).try_cast<std::remove_const_t<Type>>();
433 const auto other = internal::resolve<std::remove_cv_t<Type>>(internal::meta_context::from(*ctx));
434 return static_cast<Type *
>(
const_cast<void *
>(internal::try_cast(internal::meta_context::from(*ctx), node, other,
data())));
443 template<
typename Type>
444 [[nodiscard]] std::remove_const_t<Type>
cast()
const {
446 ENTT_ASSERT(instance,
"Invalid instance");
447 return static_cast<Type
>(*instance);
451 template<
typename Type>
452 [[nodiscard]] std::remove_const_t<Type>
cast() {
455 ENTT_ASSERT(instance,
"Invalid instance");
456 return static_cast<Type
>(*instance);
473 if(
auto other = std::as_const(*this).allow_cast(
type); other) {
475 std::swap(*
this, other);
490 template<
typename Type>
492 if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
495 auto other = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
505 template<
typename Type>
507 auto other = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
508 return allow_cast(
meta_type{*ctx, other}) && (!(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) ||
storage.
data() !=
nullptr);
512 template<
typename Type,
typename... Args>
516 node = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
517 vtable = &basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
531 vtable = &basic_vtable<void>;
547 vtable(internal::meta_traits::is_meta_sequence_container,
true,
data(), &proxy);
557 vtable(internal::meta_traits::is_meta_associative_container,
policy() ==
meta_any_policy::cref, std::as_const(*this).data(), &proxy);
564 vtable(internal::meta_traits::is_meta_associative_container,
true,
data(), &proxy);
575 vtable(internal::meta_traits::is_meta_pointer_like,
true,
storage.
data(), &ret);
583 [[nodiscard]]
explicit operator bool() const noexcept {
584 return !(node.info ==
nullptr);
589 return (ctx == other.ctx) && (((node.info ==
nullptr) && (other.node.info ==
nullptr)) || ((node.info !=
nullptr) && (other.node.info !=
nullptr) && *node.info == *other.node.info &&
storage == other.storage));
594 return !(*
this == other);
618 internal::meta_type_node node{};
619 vtable_type *vtable{&basic_vtable<void>};
629template<
typename Type>
631 return meta_any{ctx, std::in_place_type<Type &&>, std::forward<Type>(value)};
640template<
typename Type>
667 :
any{value.as_ref()} {}
674 :
any{value.as_ref()} {}
682 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
684 :
any{ctx, std::in_place_type<Type &>, value} {}
691 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
709 :
any{area, std::move(other.
any)} {}
736 [[nodiscard]]
explicit operator bool() const noexcept {
737 return static_cast<bool>(
any);
742 return (
any == other.any);
747 return !(*
this == other);
778 : node{std::move(curr)},
786 return node.value ? node.type(internal::meta_context::from(*ctx)).from_void(*ctx,
nullptr, node.value.get()) :
meta_any{
meta_ctx_arg, *ctx};
794 return node.value ? node.type(internal::meta_context::from(*ctx)).from_void(*ctx, node.value.get(),
nullptr) :
meta_any{
meta_ctx_arg, *ctx};
801 [[nodiscard]]
explicit operator bool() const noexcept {
802 return static_cast<bool>(node.type);
811 return (ctx == other.ctx && node.value == other.node.value);
815 internal::meta_prop_node node{};
816 const meta_ctx *ctx{};
826 return !(lhs == rhs);
839 : node{std::move(curr)} {}
845 template<
typename Type>
846 [[nodiscard]]
operator Type *()
const noexcept {
847 return (
type_id<Type>().hash() == node.type) ? std::static_pointer_cast<Type>(node.value).get() :
nullptr;
854 template<
typename Type>
855 [[nodiscard]]
operator Type &()
const noexcept {
856 ENTT_ASSERT(
type_id<Type>().hash() == node.type,
"Invalid type");
857 return *std::static_pointer_cast<Type>(node.value);
861 internal::meta_custom_node node{};
867 using size_type =
typename internal::meta_data_node::size_type;
894 return static_cast<bool>(node->traits & internal::meta_traits::is_const);
902 return static_cast<bool>(node->traits & internal::meta_traits::is_static);
915 template<typename Type>
918 return node->set && node->set(
meta_handle{*ctx, std::move(instance)},
meta_any{*ctx, std::forward<Type>(value)});
927 return node->get(*ctx,
meta_handle{*ctx, std::move(instance)});
941 [[nodiscard]] [[deprecated(
"use ::custom() instead")]]
meta_range<
meta_prop,
typename decltype(internal::meta_data_node::prop)::const_iterator>
prop()
const noexcept {
942 return {{*ctx, node->prop.cbegin()}, {*ctx, node->prop.cend()}};
951 for(
auto &&elem: node->prop) {
965 template<
typename Type>
966 [[nodiscard]] Type
traits() const noexcept {
967 return internal::meta_to_user_traits<Type>(node->traits);
975 return {node->custom};
982 [[nodiscard]]
explicit operator bool() const noexcept {
983 return (node !=
nullptr);
988 return (ctx == other.ctx && node == other.node);
992 const internal::meta_data_node *node{};
993 const meta_ctx *ctx{};
1003 return !(lhs == rhs);
1009 using size_type =
typename internal::meta_func_node::size_type;
1036 return static_cast<bool>(node->traits & internal::meta_traits::is_const);
1044 return static_cast<bool>(node->traits & internal::meta_traits::is_static);
1078 template<
typename... Args>
1081 std::array<
meta_any,
sizeof...(Args)> arguments{
meta_any{*ctx, std::forward<Args>(args)}...};
1082 return invoke(std::move(instance), arguments.data(),
sizeof...(Args));
1086 [[nodiscard]] [[deprecated(
"use ::custom() instead")]]
meta_range<
meta_prop,
typename decltype(internal::meta_func_node::prop)::const_iterator>
prop()
const noexcept {
1087 return {{*ctx, node->prop.cbegin()}, {*ctx, node->prop.cend()}};
1096 for(
auto &&elem: node->prop) {
1097 if(elem.id == key) {
1106 template<
typename Type>
1108 return internal::meta_to_user_traits<Type>(node->traits);
1113 return {node->custom};
1128 [[nodiscard]]
explicit operator bool() const noexcept {
1129 return (node !=
nullptr);
1134 return (ctx == other.ctx && node == other.node);
1138 const internal::meta_func_node *node{};
1139 const meta_ctx *ctx{};
1149 return !(lhs == rhs);
1154 template<
typename Func>
1155 [[nodiscard]]
auto lookup(
meta_any *
const args,
const typename internal::meta_type_node::size_type sz, [[maybe_unused]]
bool constness, Func next)
const {
1156 decltype(next()) candidate =
nullptr;
1160 for(
auto curr = next(); curr; curr = next()) {
1161 if constexpr(std::is_same_v<std::decay_t<
decltype(*curr)>, internal::meta_func_node>) {
1162 if(constness && !
static_cast<bool>(curr->traits & internal::meta_traits::is_const)) {
1167 if(curr->arity == sz) {
1172 for(; pos < sz && args[pos]; ++pos) {
1173 const auto other = curr->arg(*ctx, pos);
1174 const auto type = args[pos].type();
1176 if(
const auto &
info = other.info();
info == type.info()) {
1178 }
else if(!(type.node.conversion_helper && other.node.conversion_helper) && !(type.node.details && (internal::find_member<&internal::meta_base_node::type>(type.node.details->base,
info.
hash()) || internal::find_member<&internal::meta_conv_node::type>(type.node.details->conv,
info.
hash())))) {
1185 if(!candidate || match > same) {
1189 }
else if(match == same) {
1190 if constexpr(std::is_same_v<std::decay_t<
decltype(*curr)>, internal::meta_func_node>) {
1191 if(
static_cast<bool>(curr->traits & internal::meta_traits::is_const) !=
static_cast<bool>(candidate->traits & internal::meta_traits::is_const)) {
1192 candidate =
static_cast<bool>(candidate->traits & internal::meta_traits::is_const) ? curr : candidate;
1204 return ambiguous ? nullptr : candidate;
1209 using size_type =
typename internal::meta_type_node::size_type;
1220 : node{std::move(curr)},
1229 :
meta_type{area, curr.resolve(internal::meta_context::from(area))} {}
1252 return node.size_of;
1261 return static_cast<bool>(node.traits & internal::meta_traits::is_arithmetic);
1269 return static_cast<bool>(node.traits & internal::meta_traits::is_integral);
1277 return static_cast<bool>(node.traits & internal::meta_traits::is_signed);
1285 return static_cast<bool>(node.traits & internal::meta_traits::is_array);
1293 return static_cast<bool>(node.traits & internal::meta_traits::is_enum);
1301 return static_cast<bool>(node.traits & internal::meta_traits::is_class);
1309 return static_cast<bool>(node.traits & internal::meta_traits::is_pointer);
1318 return {*ctx, node.remove_pointer(internal::meta_context::from(*ctx))};
1326 return static_cast<bool>(node.traits & internal::meta_traits::is_meta_pointer_like);
1334 return static_cast<bool>(node.traits & internal::meta_traits::is_meta_sequence_container);
1342 return static_cast<bool>(node.traits & internal::meta_traits::is_meta_associative_container);
1352 return (node.templ.arity != 0u);
1360 return node.templ.arity;
1368 return (node.templ.resolve !=
nullptr) ?
meta_type{*ctx, node.templ.resolve(internal::meta_context::from(*ctx))} :
meta_type{};
1387 return (internal::try_cast(internal::meta_context::from(*ctx), node, other.node,
this) !=
nullptr);
1396 return (internal::try_convert(internal::meta_context::from(*ctx), node, other.info(), other.is_arithmetic() || other.is_enum(),
nullptr, [](
const void *,
auto &&...args) { return ((static_cast<void>(args), 1) + ... + 0u); }) != 0u);
1403 [[nodiscard]]
meta_range<
meta_type,
typename decltype(internal::meta_type_descriptor::base)::const_iterator>
base()
const noexcept {
1404 using range_type =
meta_range<
meta_type,
typename decltype(internal::meta_type_descriptor::base)::const_iterator>;
1405 return node.details ? range_type{{*ctx, node.details->base.cbegin()}, {*ctx, node.details->base.cend()}} : range_type{};
1412 [[nodiscard]]
meta_range<
meta_data,
typename decltype(internal::meta_type_descriptor::data)::const_iterator>
data()
const noexcept {
1413 using range_type =
meta_range<
meta_data,
typename decltype(internal::meta_type_descriptor::data)::const_iterator>;
1414 return node.details ? range_type{{*ctx, node.details->data.cbegin()}, {*ctx, node.details->data.cend()}} : range_type{};
1423 const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), node,
id);
1431 [[nodiscard]]
meta_range<
meta_func,
typename decltype(internal::meta_type_descriptor::func)::const_iterator>
func()
const noexcept {
1432 using return_type =
meta_range<
meta_func,
typename decltype(internal::meta_type_descriptor::func)::const_iterator>;
1433 return node.details ? return_type{{*ctx, node.details->func.cbegin()}, {*ctx, node.details->func.cend()}} : return_type{};
1445 const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node,
id);
1457 if(
const auto *candidate = lookup(args, sz,
false, [first = node.details->ctor.cbegin(), last = node.details->ctor.cend()]()
mutable { return first == last ? nullptr : &*(first++); }); candidate) {
1458 return candidate->invoke(*ctx, args);
1462 if(sz == 0u && (node.default_constructor !=
nullptr)) {
1463 return node.default_constructor(*ctx);
1475 template<
typename... Args>
1477 std::array<
meta_any,
sizeof...(Args)> arguments{
meta_any{*ctx, std::forward<Args>(args)}...};
1478 return construct(arguments.data(),
sizeof...(Args));
1487 return ((elem !=
nullptr) && (node.from_void !=
nullptr)) ? node.from_void(*ctx, elem,
nullptr) :
meta_any{
meta_ctx_arg, *ctx};
1492 return ((elem !=
nullptr) && (node.from_void !=
nullptr)) ? node.from_void(*ctx,
nullptr, elem) :
meta_any{
meta_ctx_arg, *ctx};
1505 if(
auto *elem = internal::find_member<&internal::meta_func_node::id>(node.details->func,
id); elem !=
nullptr) {
1506 if(
const auto *candidate = lookup(args, sz, instance && (instance->
data() ==
nullptr), [curr = elem]()
mutable { return (curr != nullptr) ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) {
1507 return candidate->invoke(*ctx,
meta_handle{*ctx, std::move(instance)}, args);
1512 for(
auto &&curr:
base()) {
1513 if(
auto elem = curr.second.invoke(
id, *instance.operator->(), args, sz); elem) {
1529 template<
typename... Args>
1532 std::array<
meta_any,
sizeof...(Args)> arguments{
meta_any{*ctx, std::forward<Args>(args)}...};
1533 return invoke(
id, std::move(instance), arguments.data(),
sizeof...(Args));
1544 template<
typename Type>
1546 const auto candidate =
data(
id);
1547 return candidate && candidate.set(std::move(instance), std::forward<Type>(value));
1557 const auto candidate =
data(
id);
1565 [[nodiscard]] [[deprecated(
"use ::custom() instead")]]
meta_range<
meta_prop,
typename decltype(internal::meta_type_descriptor::prop)::const_iterator>
prop()
const noexcept {
1566 using range_type =
meta_range<
meta_prop,
typename decltype(internal::meta_type_descriptor::prop)::const_iterator>;
1567 return node.details ? range_type{{*ctx, node.details->prop.cbegin()}, {*ctx, node.details->prop.cend()}} : range_type{};
1576 const auto *elem = internal::look_for<&internal::meta_type_descriptor::prop>(internal::meta_context::from(*ctx), node, key);
1581 template<
typename Type>
1583 return internal::meta_to_user_traits<Type>(node.traits);
1588 return {node.custom};
1595 [[nodiscard]]
explicit operator bool() const noexcept {
1596 return !(ctx ==
nullptr);
1601 return (ctx == other.ctx) && (((node.info ==
nullptr) && (other.node.info ==
nullptr)) || ((node.info !=
nullptr) && (other.node.info !=
nullptr) && *node.info == *other.node.info));
1605 internal::meta_type_node node{};
1606 const meta_ctx *ctx{};
1616 return !(lhs == rhs);
1623template<
typename... Args>
1626 return type().
invoke(
id, *
this, std::forward<Args>(args)...);
1629template<
typename... Args>
1631 return type().
invoke(
id, *
this, std::forward<Args>(args)...);
1634template<
typename Type>
1636 return type().
set(
id, *
this, std::forward<Type>(value));
1649 if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<
decltype(args)>>, internal::meta_type_node> || ...)) {
1650 return (args.from_void(*ctx,
nullptr, instance), ...);
1651 }
else if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<
decltype(args)>>, internal::meta_conv_node> || ...)) {
1652 return (args.conv(*ctx, instance), ...);
1653 }
else if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<
decltype(args)>>,
decltype(internal::meta_type_node::conversion_helper)> || ...)) {
1656 const auto value = (args(
nullptr, instance), ...);
1657 other.node.conversion_helper(other.data(), &value);
1668 return value &&
storage.assign(value.storage);
1672 if(*node.info == *other.node.info) {
1673 return storage.assign(std::move(other.storage));
1676 return assign(std::as_const(other));
1680 return meta_type{*ctx, node->type(internal::meta_context::from(*ctx))};
1684 return index < arity() ? node->arg(*ctx, index) :
meta_type{};
1688 return meta_type{*ctx, node->ret(internal::meta_context::from(*ctx))};
1692 return index < arity() ? node->arg(*ctx, index) :
meta_type{};
1696class meta_sequence_container::meta_iterator final {
1697 using vtable_type = void(
const void *,
const std::ptrdiff_t,
meta_any *);
1699 template<
typename It>
1700 static void basic_vtable(
const void *value,
const std::ptrdiff_t offset,
meta_any *other) {
1701 const auto &it = *
static_cast<const It *
>(value);
1702 other ? other->
emplace<
decltype(*it)>(*it) : std::advance(
const_cast<It &
>(it), offset);
1706 using value_type = meta_any;
1707 using pointer = input_iterator_pointer<value_type>;
1708 using reference = value_type;
1709 using difference_type = std::ptrdiff_t;
1710 using iterator_category = std::input_iterator_tag;
1711 using iterator_concept = std::bidirectional_iterator_tag;
1713 meta_iterator() =
default;
1715 template<
typename It>
1716 meta_iterator(
const meta_ctx &area, It iter) noexcept
1718 vtable{&basic_vtable<It>},
1721 meta_iterator &operator++() noexcept {
1722 vtable(
handle.data(), 1,
nullptr);
1726 meta_iterator operator++(
int value)
noexcept {
1727 meta_iterator orig = *
this;
1728 vtable(
handle.data(), ++value,
nullptr);
1732 meta_iterator &operator--() noexcept {
1733 vtable(
handle.data(), -1,
nullptr);
1737 meta_iterator operator--(
int value)
noexcept {
1738 meta_iterator orig = *
this;
1739 vtable(
handle.data(), --value,
nullptr);
1743 [[nodiscard]] reference operator*()
const {
1745 vtable(
handle.data(), 0, &other);
1749 [[nodiscard]] pointer operator->()
const {
1753 [[nodiscard]]
explicit operator bool() const noexcept {
1754 return static_cast<bool>(
handle);
1757 [[nodiscard]]
bool operator==(
const meta_iterator &other)
const noexcept {
1758 return handle == other.handle;
1761 [[nodiscard]]
bool operator!=(
const meta_iterator &other)
const noexcept {
1762 return !(*
this == other);
1765 [[nodiscard]]
const any &base() const noexcept {
1770 const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
1771 vtable_type *vtable{};
1775class meta_associative_container::meta_iterator final {
1776 using vtable_type = void(
const void *, std::pair<meta_any, meta_any> *);
1778 template<
bool KeyOnly,
typename It>
1779 static void basic_vtable(
const void *value, std::pair<meta_any, meta_any> *other) {
1780 if(
const auto &it = *
static_cast<const It *
>(value); other) {
1781 if constexpr(KeyOnly) {
1782 other->first.emplace<
decltype(*it)>(*it);
1784 other->first.emplace<
decltype((it->first))>(it->first);
1785 other->second.emplace<
decltype((it->second))>(it->second);
1788 ++
const_cast<It &
>(it);
1793 using value_type = std::pair<meta_any, meta_any>;
1794 using pointer = input_iterator_pointer<value_type>;
1795 using reference = value_type;
1796 using difference_type = std::ptrdiff_t;
1797 using iterator_category = std::input_iterator_tag;
1798 using iterator_concept = std::forward_iterator_tag;
1800 meta_iterator() =
default;
1802 template<
bool KeyOnly,
typename It>
1803 meta_iterator(
const meta_ctx &area, std::bool_constant<KeyOnly>, It iter) noexcept
1805 vtable{&basic_vtable<KeyOnly, It>},
1808 meta_iterator &operator++() noexcept {
1809 vtable(
handle.data(),
nullptr);
1813 meta_iterator operator++(
int)
noexcept {
1814 meta_iterator orig = *
this;
1815 vtable(
handle.data(),
nullptr);
1819 [[nodiscard]] reference operator*()
const {
1821 vtable(
handle.data(), &other);
1825 [[nodiscard]] pointer operator->()
const {
1829 [[nodiscard]]
explicit operator bool() const noexcept {
1830 return static_cast<bool>(
handle);
1833 [[nodiscard]]
bool operator==(
const meta_iterator &other)
const noexcept {
1834 return handle == other.handle;
1837 [[nodiscard]]
bool operator!=(
const meta_iterator &other)
const noexcept {
1838 return !(*
this == other);
1842 const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
1843 vtable_type *vtable{};
1853 return (value_type_node !=
nullptr) ?
meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} :
meta_type{};
1861 return size_fn(data);
1870 return !const_only && resize_fn(
const_cast<void *
>(data), sz);
1878 return !const_only && clear_fn(
const_cast<void *
>(data));
1887 return !const_only && reserve_fn(
const_cast<void *
>(data), sz);
1895 return begin_fn(*ctx, const_only ?
nullptr :
const_cast<void *
>(data), data);
1903 return end_fn(*ctx, const_only ?
nullptr :
const_cast<void *
>(data), data);
1914 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))}))) {
1915 const bool is_value_type = (value.
type().info() == *vtype.
info);
1916 return insert_fn(*ctx,
const_cast<void *
>(data), is_value_type ? std::as_const(value).data() :
nullptr, is_value_type ?
nullptr : std::as_const(value).data(), it);
1928 return const_only ?
iterator{} : erase_fn(*ctx,
const_cast<void *
>(data), it);
1938 it.operator++(
static_cast<int>(pos) - 1);
1946[[nodiscard]]
inline meta_sequence_container::operator bool() const noexcept {
1947 return (data !=
nullptr);
1955 return (key_type_node !=
nullptr) ?
meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))} :
meta_type{};
1963 return (mapped_type_node !=
nullptr) ?
meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))} :
meta_type{};
1968 return (value_type_node !=
nullptr) ?
meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} :
meta_type{};
1973 return size_fn(data);
1978 return !const_only && clear_fn(
const_cast<void *
>(data));
1983 return !const_only && reserve_fn(
const_cast<void *
>(data), sz);
1988 return begin_fn(*ctx, const_only ?
nullptr :
const_cast<void *
>(data), data);
1993 return end_fn(*ctx, const_only ?
nullptr :
const_cast<void *
>(data), data);
2003 return !const_only && key.
allow_cast(
meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})
2004 && ((mapped_type_node ==
nullptr) || value.allow_cast(meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))}))
2005 && insert_fn(
const_cast<void *
>(data), std::as_const(key).data(), std::as_const(value).data());
2014 return (!const_only && key.
allow_cast(
meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})) ? erase_fn(
const_cast<void *
>(data), std::as_const(key).data()) : 0u;
2023 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, std::as_const(key).data()) :
iterator{};
2030[[nodiscard]]
inline meta_associative_container::operator bool() const noexcept {
2031 return (data !=
nullptr);
A SBO friendly, type-safe container for single values of any type.
pointer data() const noexcept
Direct access to the internal packed array.
deletion_policy policy() const noexcept
Returns the deletion policy of a sparse set.
value_type & emplace(const entity_type entt, Args &&...args)
Assigns an entity to a storage and constructs its object.
Service locator, nothing more.
static Service & value_or(Args &&...args)
Returns a service if available or sets it from a fallback type.
basic_handle< registry > handle
Alias declaration for the most common use case.
std::uint32_t id_type
Alias declaration for type identifiers.
basic_any<> any
Alias declaration for the most common use case.
constexpr bool is_complete_v
Helper variable template.
constexpr get_t< Type... > get
Variable template for lists of observed elements.
meta_type resolve() noexcept
Returns the meta type associated with a given type.
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.
meta_any forward_as_meta(const meta_ctx &ctx, Type &&value)
Forwards its argument and avoids copies for lvalue references.
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
const type_info & type_id() noexcept
Returns the type info object associated to a given type.
any_policy
Possible modes of an any object.
@ ref
Aliasing mode, the object points to a non-const element.
@ cref
Const aliasing mode, the object points to a const element.
@ owner
Default mode, the object owns the contained element.
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
Utility class to create an iterable object from a pair of iterators.
Implementation specific information about a type.
constexpr id_type hash() const noexcept
Type hash.