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"
49 template<
typename Type>
53 value_type_node{&internal::resolve<typename Type::value_type>},
54 const_reference_node{&internal::resolve<std::remove_const_t<std::remove_reference_t<typename Type::const_reference>>>},
55 size_fn{meta_sequence_container_traits<std::remove_const_t<Type>>
::size},
56 clear_fn{meta_sequence_container_traits<std::remove_const_t<Type>>
::clear},
57 reserve_fn{meta_sequence_container_traits<std::remove_const_t<Type>>
::reserve},
58 resize_fn{meta_sequence_container_traits<std::remove_const_t<Type>>
::resize},
59 begin_fn{meta_sequence_container_traits<std::remove_const_t<Type>>
::begin},
60 end_fn{meta_sequence_container_traits<std::remove_const_t<Type>>
::end},
61 insert_fn{meta_sequence_container_traits<std::remove_const_t<Type>>
::insert},
62 erase_fn{meta_sequence_container_traits<std::remove_const_t<Type>>
::erase},
63 const_only{std::is_const_v<Type>} {}
65 [[nodiscard]]
inline meta_type
value_type() const noexcept;
74 [[nodiscard]] inline meta_any operator[](
size_type);
75 [[nodiscard]] inline explicit operator
bool() const noexcept;
78 const meta_ctx *ctx{};
80 internal::meta_type_node (*value_type_node)(
const internal::meta_context &){};
81 internal::meta_type_node (*const_reference_node)(
const internal::meta_context &){};
83 bool (*clear_fn)(
void *){};
84 bool (*reserve_fn)(
void *,
const size_type){};
85 bool (*resize_fn)(
void *,
const size_type){};
86 iterator (*begin_fn)(
const meta_ctx &,
void *,
const void *){};
87 iterator (*end_fn)(
const meta_ctx &,
void *,
const void *){};
88 iterator (*insert_fn)(
const meta_ctx &,
void *,
const void *,
const void *,
const iterator &){};
112 template<
typename Type>
116 key_type_node{&internal::resolve<typename Type::key_type>},
117 value_type_node{&internal::resolve<typename Type::value_type>},
118 size_fn{&meta_associative_container_traits<std::remove_const_t<Type>>
::size},
119 clear_fn{&meta_associative_container_traits<std::remove_const_t<Type>>
::clear},
120 reserve_fn{&meta_associative_container_traits<std::remove_const_t<Type>>
::reserve},
121 begin_fn{&meta_associative_container_traits<std::remove_const_t<Type>>
::begin},
122 end_fn{&meta_associative_container_traits<std::remove_const_t<Type>>
::end},
123 insert_fn{&meta_associative_container_traits<std::remove_const_t<Type>>
::insert},
124 erase_fn{&meta_associative_container_traits<std::remove_const_t<Type>>
::erase},
125 find_fn{&meta_associative_container_traits<std::remove_const_t<Type>>
::find},
126 const_only{std::is_const_v<Type>} {
127 if constexpr(!meta_associative_container_traits<std::remove_const_t<Type>>::key_only) {
128 mapped_type_node = &internal::resolve<typename Type::mapped_type>;
132 [[nodiscard]]
inline meta_type
key_type() const noexcept;
133 [[nodiscard]] inline meta_type
mapped_type() const noexcept;
134 [[nodiscard]] inline meta_type
value_type() const noexcept;
140 inline
bool insert(meta_any, meta_any);
143 [[nodiscard]] inline explicit operator
bool() const noexcept;
146 const meta_ctx *ctx{};
148 internal::meta_type_node (*key_type_node)(
const internal::meta_context &){};
149 internal::meta_type_node (*mapped_type_node)(
const internal::meta_context &){};
150 internal::meta_type_node (*value_type_node)(
const internal::meta_context &){};
152 bool (*clear_fn)(
void *){};
153 bool (*reserve_fn)(
void *,
const size_type){};
154 iterator (*begin_fn)(
const meta_ctx &,
void *,
const void *){};
155 iterator (*end_fn)(
const meta_ctx &,
void *,
const void *){};
156 bool (*insert_fn)(
void *,
const void *,
const void *){};
157 size_type (*erase_fn)(
void *,
const void *){};
158 iterator (*find_fn)(
const meta_ctx &,
void *,
const void *,
const void *){};
163using meta_any_policy [[deprecated(
"use any_policy instead")]] =
any_policy;
167 using vtable_type = void(
const internal::meta_traits op,
const meta_ctx &,
const void *,
void *);
169 template<
typename Type>
170 static void basic_vtable([[maybe_unused]]
const internal::meta_traits req, [[maybe_unused]]
const meta_ctx &area, [[maybe_unused]]
const void *value, [[maybe_unused]]
void *other) {
171 static_assert(std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>,
"Invalid type");
174 if(!!(req & internal::meta_traits::is_pointer_like)) {
175 if constexpr(std::is_function_v<typename std::pointer_traits<Type>::element_type>) {
176 static_cast<meta_any *
>(other)->
emplace<Type>(*
static_cast<const Type *
>(value));
177 }
else if constexpr(!std::is_void_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) {
180 if constexpr(std::is_constructible_v<bool, Type>) {
181 if(
const auto &pointer_like = *
static_cast<const Type *
>(value); pointer_like) {
192 if(!!(req & internal::meta_traits::is_sequence_container)) {
199 if(!!(req & internal::meta_traits::is_associative_container)) {
207 if(storage.owner() && (node.dtor.dtor !=
nullptr)) {
208 node.dtor.dtor(storage.data());
213 : storage{std::move(
ref)},
215 if(storage || !other.storage) {
217 vtable = other.vtable;
238 template<
typename Type,
typename... Args>
239 explicit meta_any(std::in_place_type_t<Type>, Args &&...args)
240 : meta_any{
locator<
meta_ctx>::value_or(), std::in_place_type<Type>, std::forward<Args>(args)...} {}
239 explicit meta_any(std::in_place_type_t<Type>, Args &&...args) {
…}
249 template<
typename Type,
typename... Args>
251 : storage{std::in_place_type<Type>, std::forward<Args>(args)...},
253 node{internal::
resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx))},
254 vtable{&basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>} {}
261 template<
typename Type>
271 template<
typename Type>
276 node = internal::resolve<Type>(internal::meta_context::from(*ctx));
277 vtable = &basic_vtable<Type>;
286 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
288 : meta_any{
locator<
meta_ctx>::value_or(), std::forward<Type>(value)} {}
296 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
298 : meta_any{area, std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
306 : storage{other.storage},
308 node{(other.node.
resolve != nullptr) ? other.node.
resolve(internal::meta_context::from(*ctx)) : other.node},
309 vtable{other.vtable} {}
317 : storage{std::move(other.storage)},
319 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{})},
320 vtable{std::exchange(other.vtable, nullptr)} {}
333 : storage{std::move(other.storage)},
335 node{std::exchange(other.node, internal::meta_type_node{})},
336 vtable{std::exchange(other.vtable,
nullptr)} {}
351 storage = other.storage;
354 vtable = other.vtable;
371 storage = std::move(other.storage);
373 node = std::exchange(other.node, internal::meta_type_node{});
374 vtable = std::exchange(other.vtable,
nullptr);
384 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
394 [[nodiscard]] [[deprecated(
"use ::base().data() instead")]] const
void *
data() const noexcept {
395 return storage.data();
394 [[nodiscard]] [[deprecated(
"use ::base().data() instead")]] const
void *
data() const noexcept {
…}
399 [[nodiscard]] [[deprecated(
"no longer supported, use ::base().data() for const access")]]
void *
data() noexcept {
400 return storage.data();
399 [[nodiscard]] [[deprecated(
"no longer supported, use ::base().data() for const access")]]
void *
data() noexcept {
…}
410 template<
typename... Args>
414 template<
typename... Args>
424 template<
typename Type>
442 template<
typename Type>
445 return static_cast<const Type *
>(internal::try_cast(internal::meta_context::from(*ctx), node, other, storage.data()));
449 template<
typename Type>
451 if constexpr(std::is_const_v<Type>) {
452 return std::as_const(*this).try_cast<std::remove_const_t<Type>>();
456 return static_cast<Type *
>(
const_cast<void *
>(internal::try_cast(internal::meta_context::from(*ctx), node, other, storage.data())));
465 template<
typename Type>
466 [[nodiscard]] std::remove_const_t<Type>
cast()
const {
468 ENTT_ASSERT(instance,
"Invalid instance");
469 return static_cast<Type
>(*instance);
466 [[nodiscard]] std::remove_const_t<Type>
cast()
const {
…}
473 template<
typename Type>
474 [[nodiscard]] std::remove_const_t<Type>
cast() {
477 ENTT_ASSERT(instance,
"Invalid instance");
478 return static_cast<Type
>(*instance);
474 [[nodiscard]] std::remove_const_t<Type>
cast() {
…}
495 if(
auto other = std::as_const(*this).allow_cast(
type); other) {
496 if(other.storage.owner()) {
497 std::swap(*
this, other);
512 template<
typename Type>
514 if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
518 return ((node.info !=
nullptr) && (*node.info ==
entt::type_id<Type>())) ?
as_ref() :
allow_cast(
meta_type{*ctx, internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx))});
527 template<
typename Type>
529 if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
533 return ((node.info !=
nullptr) && (*node.info ==
entt::type_id<Type>())) ||
allow_cast(
meta_type{*ctx, internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx))});
538 template<
typename Type,
typename... Args>
541 storage.emplace<Type>(std::forward<Args>(args)...);
542 node = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
543 vtable = &basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
566 if(!proxy && vtable !=
nullptr) { vtable(internal::meta_traits::is_sequence_container, *ctx, storage.data(), &proxy); }
573 if(vtable !=
nullptr) { vtable(internal::meta_traits::is_sequence_container | internal::meta_traits::is_const, *ctx, storage.data(), &proxy); }
583 if(!proxy && vtable !=
nullptr) { vtable(internal::meta_traits::is_associative_container, *ctx, storage.data(), &proxy); }
590 if(vtable !=
nullptr) { vtable(internal::meta_traits::is_associative_container | internal::meta_traits::is_const, *ctx, storage.data(), &proxy); }
601 if(vtable !=
nullptr) { vtable(internal::meta_traits::is_pointer_like, *ctx, storage.data(), &ret); }
609 [[nodiscard]]
explicit operator bool() const noexcept {
610 return !(node.info ==
nullptr);
609 [[nodiscard]]
explicit operator bool() const noexcept {
…}
614 [[nodiscard]]
bool operator==(
const meta_any &other)
const noexcept {
615 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));
614 [[nodiscard]]
bool operator==(
const meta_any &other)
const noexcept {
…}
619 [[nodiscard]]
bool operator!=(
const meta_any &other)
const noexcept {
620 return !(*
this == other);
619 [[nodiscard]]
bool operator!=(
const meta_any &other)
const noexcept {
…}
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()};
629 [[nodiscard]] meta_any
as_ref() const noexcept {
…}
637 [[nodiscard]] [[deprecated(
"use ::base().policy() instead")]]
any_policy policy() const noexcept {
638 return storage.policy();
637 [[nodiscard]] [[deprecated(
"use ::base().policy() instead")]]
any_policy policy() const noexcept {
…}
645 [[nodiscard]]
const any &
base() const noexcept {
660 internal::meta_type_node node{};
661 vtable_type *vtable{};
671template<
typename Type>
673 return meta_any{ctx, std::in_place_type<Type &&>, std::forward<Type>(value)};
682template<
typename Type>
704 : any{value.as_ref()} {}
711 : any{value.as_ref()} {}
719 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
721 : any{ctx, std::in_place_type<Type &>, value} {}
728 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
730 : any{std::in_place_type<Type &>, value} {}
738 : any{area, other.any} {}
746 : any{area, std::move(other.any)} {}
773 [[nodiscard]]
explicit operator bool() const noexcept {
774 return static_cast<bool>(any);
773 [[nodiscard]]
explicit operator bool() const noexcept {
…}
779 return (any == other.any);
784 return !(*
this == other);
814 : node{std::move(curr)} {}
820 template<
typename Type>
821 [[nodiscard]]
operator Type *()
const noexcept {
822 return (
type_id<Type>().hash() == node.type) ? std::static_pointer_cast<Type>(node.value).get() :
nullptr;
821 [[nodiscard]]
operator Type *()
const noexcept {
…}
829 template<
typename Type>
830 [[nodiscard]]
operator Type &()
const noexcept {
831 ENTT_ASSERT(
type_id<Type>().hash() == node.type,
"Invalid type");
832 return *std::static_pointer_cast<Type>(node.value);
830 [[nodiscard]]
operator Type &()
const noexcept {
…}
836 internal::meta_custom_node node{};
842 using size_type =
typename internal::meta_data_node::size_type;
853 : node{std::move(curr)},
869 return static_cast<bool>(node.traits & internal::meta_traits::is_const);
877 return static_cast<bool>(node.traits & internal::meta_traits::is_static);
890 template<typename Type>
893 return (node.set !=
nullptr) && node.set(
meta_handle{*ctx, std::move(instance)},
meta_any{*ctx, std::forward<Type>(value)});
917 template<
typename Type>
918 [[nodiscard]] Type
traits() const noexcept {
919 return internal::meta_to_user_traits<Type>(node.traits);
918 [[nodiscard]] Type
traits() const noexcept {
…}
927 return {node.custom};
934 [[nodiscard]]
explicit operator bool() const noexcept {
935 return (node.get !=
nullptr);
934 [[nodiscard]]
explicit operator bool() const noexcept {
…}
944 return (ctx == other.ctx) && (node.set == other.node.set) && (node.get == other.node.get);
948 internal::meta_data_node node{};
959 return !(lhs == rhs);
965 using size_type =
typename internal::meta_func_node::size_type;
976 : node{std::move(curr)},
992 return static_cast<bool>(node.traits & internal::meta_traits::is_const);
1000 return static_cast<bool>(node.traits & internal::meta_traits::is_static);
1024 return ((node.invoke !=
nullptr) && (sz ==
arity())) ? node.invoke(
meta_handle{*ctx, std::move(instance)}, args) :
meta_any{meta_ctx_arg, *ctx};
1034 template<
typename... Args>
1037 return invoke(std::move(instance), std::array<
meta_any,
sizeof...(Args)>{
meta_any{*ctx, std::forward<Args>(args)}...}.
data(),
sizeof...(Args));
1041 template<
typename Type>
1043 return internal::meta_to_user_traits<Type>(node.traits);
1048 return {node.custom};
1063 [[nodiscard]]
explicit operator bool() const noexcept {
1064 return (node.invoke !=
nullptr);
1063 [[nodiscard]]
explicit operator bool() const noexcept {
…}
1069 return (ctx == other.ctx) && (node.invoke == other.node.invoke);
1073 internal::meta_func_node node{};
1084 return !(lhs == rhs);
1089 template<
typename Func>
1090 [[nodiscard]]
auto lookup(
meta_any *
const args,
const typename internal::meta_type_node::size_type sz, [[maybe_unused]]
bool constness, Func next)
const {
1091 decltype(next()) candidate =
nullptr;
1095 for(
auto curr = next(); curr; curr = next()) {
1096 if constexpr(std::is_same_v<std::decay_t<
decltype(*curr)>, internal::meta_func_node>) {
1097 if(constness && !
static_cast<bool>(curr->traits & internal::meta_traits::is_const)) {
1102 if(curr->arity == sz) {
1107 for(; pos < sz && args[pos]; ++pos) {
1108 const auto other = curr->arg(*ctx, pos);
1109 const auto type = args[pos].type();
1111 if(
const auto &
info = other.info();
info == type.info()) {
1113 }
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())))) {
1120 if(!candidate || match > same) {
1124 }
else if(match == same) {
1125 if constexpr(std::is_same_v<std::decay_t<
decltype(*curr)>, internal::meta_func_node>) {
1126 if(
static_cast<bool>(curr->traits & internal::meta_traits::is_const) !=
static_cast<bool>(candidate->traits & internal::meta_traits::is_const)) {
1127 candidate =
static_cast<bool>(candidate->traits & internal::meta_traits::is_const) ? curr : candidate;
1139 return ambiguous ? nullptr : candidate;
1144 using size_type =
typename internal::meta_type_node::size_type;
1155 : node{std::move(curr)},
1164 :
meta_type{area, curr.resolve(internal::meta_context::from(area))} {}
1171 return (node.info !=
nullptr) ? *node.info :
type_id<void>();
1187 return node.size_of;
1196 return static_cast<bool>(node.traits & internal::meta_traits::is_arithmetic);
1204 return static_cast<bool>(node.traits & internal::meta_traits::is_integral);
1212 return static_cast<bool>(node.traits & internal::meta_traits::is_signed);
1220 return static_cast<bool>(node.traits & internal::meta_traits::is_array);
1228 return static_cast<bool>(node.traits & internal::meta_traits::is_enum);
1236 return static_cast<bool>(node.traits & internal::meta_traits::is_class);
1244 return static_cast<bool>(node.traits & internal::meta_traits::is_pointer);
1253 return (node.remove_pointer !=
nullptr) ?
meta_type{*ctx, node.remove_pointer(internal::meta_context::from(*ctx))} : *
this;
1261 return static_cast<bool>(node.traits & internal::meta_traits::is_pointer_like);
1269 return static_cast<bool>(node.traits & internal::meta_traits::is_sequence_container);
1277 return static_cast<bool>(node.traits & internal::meta_traits::is_associative_container);
1287 return (node.templ.arity != 0u);
1295 return node.templ.arity;
1303 return (node.templ.resolve !=
nullptr) ?
meta_type{*ctx, node.templ.resolve(internal::meta_context::from(*ctx))} :
meta_type{};
1322 return other && (internal::try_cast(internal::meta_context::from(*ctx), node, *other.node.info,
this) !=
nullptr);
1331 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);
1338 [[nodiscard]]
meta_range<
meta_type,
typename decltype(internal::meta_type_descriptor::base)::const_iterator>
base()
const noexcept {
1339 using range_type =
meta_range<
meta_type,
typename decltype(internal::meta_type_descriptor::base)::const_iterator>;
1340 return node.details ? range_type{{*ctx, node.details->base.cbegin()}, {*ctx, node.details->base.cend()}} : range_type{};
1347 [[nodiscard]]
meta_range<
meta_data,
typename decltype(internal::meta_type_descriptor::data)::const_iterator>
data()
const noexcept {
1348 using range_type =
meta_range<
meta_data,
typename decltype(internal::meta_type_descriptor::data)::const_iterator>;
1349 return node.details ? range_type{{*ctx, node.details->data.cbegin()}, {*ctx, node.details->data.cend()}} : range_type{};
1358 const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), node,
id);
1366 [[nodiscard]]
meta_range<
meta_func,
typename decltype(internal::meta_type_descriptor::func)::const_iterator>
func()
const noexcept {
1367 using return_type =
meta_range<
meta_func,
typename decltype(internal::meta_type_descriptor::func)::const_iterator>;
1368 return node.details ? return_type{{*ctx, node.details->func.cbegin()}, {*ctx, node.details->func.cend()}} : return_type{};
1377 const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node,
id);
1389 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) {
1390 return candidate->invoke(*ctx, args);
1394 if(sz == 0u && (node.default_constructor !=
nullptr)) {
1395 return node.default_constructor(*ctx);
1407 template<
typename... Args>
1420 return ((elem !=
nullptr) && (node.from_void !=
nullptr)) ? node.from_void(*ctx, elem, transfer_ownership ? elem :
nullptr) :
meta_any{
meta_ctx_arg, *ctx};
1429 return ((elem !=
nullptr) && (node.from_void !=
nullptr)) ? node.from_void(*ctx,
nullptr, elem) :
meta_any{
meta_ctx_arg, *ctx};
1443 if(
auto *elem = internal::find_member<&internal::meta_func_node::id>(node.details->func,
id); elem !=
nullptr) {
1444 if(
const auto *candidate = lookup(args, sz, (instance->
base().
policy() ==
any_policy::cref), [curr = elem]()
mutable { return (curr != nullptr) ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) {
1445 return candidate->invoke(
meta_handle{*ctx, std::move(instance)}, args);
1450 for(
auto &&curr:
base()) {
1451 if(
auto elem = curr.second.invoke(
id, *instance.operator->(), args, sz); elem) {
1467 template<
typename... Args>
1470 return invoke(
id, std::move(instance), std::array<
meta_any,
sizeof...(Args)>{
meta_any{*ctx, std::forward<Args>(args)}...}.
data(),
sizeof...(Args));
1481 template<
typename Type>
1484 const auto candidate =
data(
id);
1485 return candidate && candidate.set(std::move(instance), std::forward<Type>(value));
1495 const auto candidate =
data(
id);
1500 template<
typename Type>
1502 return internal::meta_to_user_traits<Type>(node.traits);
1507 return {node.custom};
1514 [[nodiscard]]
explicit operator bool() const noexcept {
1515 return (node.info !=
nullptr);
1514 [[nodiscard]]
explicit operator bool() const noexcept {
…}
1521 return (ctx == other.ctx) && ((node.info ==
nullptr) == (other.node.info ==
nullptr)) && (node.info ==
nullptr || (*node.info == *other.node.info));
1525 internal::meta_type_node node{};
1536 return !(lhs == rhs);
1543template<
typename... Args>
1546 return type().
invoke(
id, *
this, std::forward<Args>(args)...);
1549template<
typename... Args>
1551 return type().
invoke(
id, *
this, std::forward<Args>(args)...);
1554template<
typename Type>
1556 return type().
set(
id, *
this, std::forward<Type>(value));
1568 return internal::try_convert(internal::meta_context::from(*ctx), node,
type.info(),
type.is_arithmetic() ||
type.is_enum(), storage.data(), [
this, &
type]([[maybe_unused]]
const void *instance, [[maybe_unused]]
auto &&...args) {
1569 if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<decltype(args)>>, internal::meta_type_node> || ...)) {
1570 return (args.from_void(*ctx, nullptr, instance), ...);
1571 }
else if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<
decltype(args)>>, internal::meta_conv_node> || ...)) {
1572 return (args.conv(*ctx, instance), ...);
1573 }
else if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<
decltype(args)>>,
decltype(internal::meta_type_node::conversion_helper)> || ...)) {
1575 auto other = type.construct();
1576 const auto value = (args(nullptr, instance), ...);
1577 other.node.conversion_helper(other.storage.data(), &value);
1581 return meta_any{meta_ctx_arg, *ctx, std::forward<decltype(args)>(args)...};
1588 return value && storage.
assign(value.storage);
1592 if(*node.info == *other.node.info) {
1593 return storage.assign(std::move(other.storage));
1596 return assign(std::as_const(other));
1600 return (node.type !=
nullptr) ?
meta_type{*ctx, node.type(internal::meta_context::from(*ctx))} :
meta_type{};
1608 return (node.ret !=
nullptr) ?
meta_type{*ctx, node.ret(internal::meta_context::from(*ctx))} :
meta_type{};
1616class meta_sequence_container::meta_iterator final {
1617 using vtable_type = void(
const void *,
const std::ptrdiff_t,
meta_any *);
1619 template<
typename It>
1620 static void basic_vtable(
const void *value,
const std::ptrdiff_t offset,
meta_any *other) {
1621 const auto &it = *
static_cast<const It *
>(value);
1622 other ? other->
emplace<
decltype(*it)>(*it) : std::advance(
const_cast<It &
>(it), offset);
1626 using value_type = meta_any;
1627 using pointer = input_iterator_pointer<value_type>;
1628 using reference = value_type;
1629 using difference_type = std::ptrdiff_t;
1630 using iterator_category = std::input_iterator_tag;
1631 using iterator_concept = std::bidirectional_iterator_tag;
1633 meta_iterator() =
default;
1635 template<
typename It>
1636 meta_iterator(
const meta_ctx &area, It iter) noexcept
1638 vtable{&basic_vtable<It>},
1641 meta_iterator &operator++() noexcept {
1642 vtable(
handle.data(), 1,
nullptr);
1646 meta_iterator operator++(
int value)
noexcept {
1647 meta_iterator orig = *
this;
1648 vtable(
handle.data(), ++value,
nullptr);
1652 meta_iterator &operator--() noexcept {
1653 vtable(
handle.data(), -1,
nullptr);
1657 meta_iterator operator--(
int value)
noexcept {
1658 meta_iterator orig = *
this;
1659 vtable(
handle.data(), --value,
nullptr);
1663 [[nodiscard]] reference operator*()
const {
1665 vtable(
handle.data(), 0, &other);
1669 [[nodiscard]] pointer operator->()
const {
1673 [[nodiscard]]
explicit operator bool() const noexcept {
1674 return (vtable !=
nullptr);
1677 [[nodiscard]]
bool operator==(
const meta_iterator &other)
const noexcept {
1678 return handle == other.handle;
1681 [[nodiscard]]
bool operator!=(
const meta_iterator &other)
const noexcept {
1682 return !(*
this == other);
1685 [[nodiscard]]
const any &base() const noexcept {
1690 const meta_ctx *ctx{};
1691 vtable_type *vtable{};
1695class meta_associative_container::meta_iterator final {
1696 using vtable_type = void(
const void *, std::pair<meta_any, meta_any> *);
1698 template<
bool KeyOnly,
typename It>
1699 static void basic_vtable(
const void *value, std::pair<meta_any, meta_any> *other) {
1700 if(
const auto &it = *
static_cast<const It *
>(value); other) {
1701 if constexpr(KeyOnly) {
1702 other->first.emplace<
decltype(*it)>(*it);
1704 other->first.emplace<
decltype((it->first))>(it->first);
1705 other->second.emplace<
decltype((it->second))>(it->second);
1708 ++
const_cast<It &
>(it);
1713 using value_type = std::pair<meta_any, meta_any>;
1714 using pointer = input_iterator_pointer<value_type>;
1715 using reference = value_type;
1716 using difference_type = std::ptrdiff_t;
1717 using iterator_category = std::input_iterator_tag;
1718 using iterator_concept = std::forward_iterator_tag;
1720 meta_iterator() =
default;
1722 template<
bool KeyOnly,
typename It>
1723 meta_iterator(
const meta_ctx &area, std::bool_constant<KeyOnly>, It iter) noexcept
1725 vtable{&basic_vtable<KeyOnly, It>},
1728 meta_iterator &operator++() noexcept {
1729 vtable(
handle.data(),
nullptr);
1733 meta_iterator operator++(
int)
noexcept {
1734 meta_iterator orig = *
this;
1735 vtable(
handle.data(),
nullptr);
1739 [[nodiscard]] reference operator*()
const {
1741 vtable(
handle.data(), &other);
1745 [[nodiscard]] pointer operator->()
const {
1749 [[nodiscard]]
explicit operator bool() const noexcept {
1750 return (vtable !=
nullptr);
1753 [[nodiscard]]
bool operator==(
const meta_iterator &other)
const noexcept {
1754 return handle == other.handle;
1757 [[nodiscard]]
bool operator!=(
const meta_iterator &other)
const noexcept {
1758 return !(*
this == other);
1762 const meta_ctx *ctx{};
1763 vtable_type *vtable{};
1773 return (value_type_node !=
nullptr) ?
meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} :
meta_type{};
1781 return size_fn(data);
1790 return !const_only && resize_fn(
const_cast<void *
>(data), sz);
1798 return !const_only && clear_fn(
const_cast<void *
>(data));
1807 return !const_only && reserve_fn(
const_cast<void *
>(data), sz);
1815 return begin_fn(*ctx, const_only ?
nullptr :
const_cast<void *
>(data), data);
1823 return end_fn(*ctx, const_only ?
nullptr :
const_cast<void *
>(data), data);
1834 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))}))) {
1835 const bool is_value_type = (value.
type().info() == *vtype.
info);
1836 return insert_fn(*ctx,
const_cast<void *
>(data), is_value_type ? value.
base().
data() :
nullptr, is_value_type ?
nullptr : value.
base().
data(), it);
1848 return const_only ?
iterator{} : erase_fn(*ctx,
const_cast<void *
>(data), it);
1858 it.operator++(
static_cast<int>(pos) - 1);
1866[[nodiscard]]
inline meta_sequence_container::operator bool() const noexcept {
1867 return (data !=
nullptr);
1866[[nodiscard]]
inline meta_sequence_container::operator bool() const noexcept {
…}
1875 return (key_type_node !=
nullptr) ?
meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))} :
meta_type{};
1883 return (mapped_type_node !=
nullptr) ?
meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))} :
meta_type{};
1888 return (value_type_node !=
nullptr) ?
meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} :
meta_type{};
1893 return size_fn(data);
1898 return !const_only && clear_fn(
const_cast<void *
>(data));
1903 return !const_only && reserve_fn(
const_cast<void *
>(data), sz);
1908 return begin_fn(*ctx, const_only ?
nullptr :
const_cast<void *
>(data), data);
1913 return end_fn(*ctx, const_only ?
nullptr :
const_cast<void *
>(data), data);
1923 return !const_only && key.
allow_cast(
meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})
1924 && ((mapped_type_node ==
nullptr) || value.allow_cast(meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))}))
1925 && insert_fn(
const_cast<void *
>(data), key.
base().
data(), value.base().data());
1934 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;
1943 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{};
1950[[nodiscard]]
inline meta_associative_container::operator bool() const noexcept {
1951 return (data !=
nullptr);
1950[[nodiscard]]
inline meta_associative_container::operator bool() const noexcept {
…}
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.
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.
iterable_adaptor< internal::meta_range_iterator< Type, It > > meta_range
Iterable range to use to iterate all types of meta objects.
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.
@ in_place
In-place deletion policy.
meta_any forward_as_meta(const meta_ctx &ctx, Type &&value)
Forwards its argument and avoids copies for lvalue references.
meta_type resolve(const meta_ctx &ctx) noexcept
Returns the meta type associated with a given type.
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.
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
basic_storage< Type > storage
Alias declaration for the most common use case.
Implementation specific information about a type.