EnTT 4.0.0
Loading...
Searching...
No Matches
meta.hpp
1#ifndef ENTT_META_META_HPP
2#define ENTT_META_META_HPP
3
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"
22#include "context.hpp"
23#include "fwd.hpp"
24#include "node.hpp"
25#include "range.hpp"
26#include "type_traits.hpp"
27
28namespace entt {
29
31namespace internal {
32
33template<typename Type>
34struct basic_meta_object {
35 [[nodiscard]] auto &node_or_assert() const noexcept {
36 ENTT_ASSERT(node != nullptr, "Invalid pointer to node");
37 return *node;
38 }
39
40 const Type *node{};
41 const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
42};
43
44} // namespace internal
46
49 class meta_iterator;
50
51public:
53 using size_type = stl::size_t;
55 using iterator = meta_iterator;
56
59
66 template<typename Type>
67 meta_sequence_container(const meta_ctx &area, Type &instance) noexcept
68 : ctx{&area},
69 data{&instance},
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>} {}
80
81 [[nodiscard]] inline meta_type value_type() const noexcept;
82 [[nodiscard]] inline size_type size() const noexcept;
83 inline bool resize(size_type);
84 inline bool clear();
85 inline bool reserve(size_type);
86 [[nodiscard]] inline iterator begin();
87 [[nodiscard]] inline iterator end();
88 inline iterator insert(const iterator &, meta_any);
89 inline iterator erase(const iterator &);
90 [[nodiscard]] inline meta_any operator[](size_type);
91 [[nodiscard]] inline explicit operator bool() const noexcept;
92
93private:
94 const meta_ctx *ctx{};
95 const void *data{};
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 &){};
98 size_type (*size_fn)(const void *){};
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 &){};
104 iterator (*erase_fn)(const meta_ctx &, void *, const iterator &){};
105 bool const_only{};
106};
107
110 class meta_iterator;
111
112public:
114 using size_type = stl::size_t;
116 using iterator = meta_iterator;
117
120
127 template<typename Type>
128 meta_associative_container(const meta_ctx &area, Type &instance) noexcept
129 : ctx{&area},
130 data{&instance},
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>;
143 }
144 }
145
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;
149 [[nodiscard]] inline size_type size() const noexcept;
150 inline bool clear();
151 inline bool reserve(size_type);
152 [[nodiscard]] inline iterator begin();
153 [[nodiscard]] inline iterator end();
154 inline bool insert(meta_any, meta_any);
155 inline size_type erase(meta_any);
156 [[nodiscard]] inline iterator find(meta_any);
157 [[nodiscard]] inline explicit operator bool() const noexcept;
158
159private:
160 const meta_ctx *ctx{};
161 const void *data{};
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 &){};
165 size_type (*size_fn)(const void *){};
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 *){};
172 bool const_only{};
173};
174
176class meta_any {
177 using vtable_type = void(const internal::meta_traits, const meta_any &, void *);
178
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));
183 }
184
185 if constexpr(is_meta_pointer_like_v<Type>) {
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>) {
189 if(const auto &pointer_like = any_cast<const Type &>(value.storage); pointer_like) {
190 static_cast<meta_any *>(other)->emplace<decltype(adl_meta_pointer_like<Type>::dereference(stl::declval<const Type &>()))>(adl_meta_pointer_like<Type>::dereference(pointer_like));
191 }
192 } else {
193 static_cast<meta_any *>(other)->emplace<decltype(adl_meta_pointer_like<Type>::dereference(stl::declval<const Type &>()))>(adl_meta_pointer_like<Type>::dereference(any_cast<const Type &>(value.storage)));
194 }
195 }
196 }
197 } else if constexpr(requires(Type elem) { *elem; }) {
198 if(req == internal::meta_traits::is_pointer) {
199 if constexpr(stl::is_class_v<Type>) {
200 if(const auto &elem = any_cast<const Type &>(value.storage); elem) {
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));
202 }
203 } else if constexpr(!stl::is_array_v<Type> && !stl::is_void_v<stl::remove_const_t<stl::remove_pointer_t<Type>>>) {
204 if(auto *pointer = any_cast<Type>(value.storage); pointer) {
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);
206 }
207 }
208 }
210 if(constexpr auto flag = (is_complete_v<meta_sequence_container_traits<Type>> ? internal::meta_traits::is_sequence_container : internal::meta_traits::is_associative_container); req == flag) {
211 using container_type = stl::conditional_t<is_complete_v<meta_sequence_container_traits<Type>>, meta_sequence_container, meta_associative_container>;
212 *static_cast<container_type *>(other) = (value.storage.policy() == any_policy::cref) ? container_type{*value.ctx, any_cast<const Type &>(value.storage)} : container_type{*value.ctx, any_cast<Type &>(const_cast<meta_any &>(value).storage)};
213 }
214 }
215 }
216
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);
221 }
222
223 ENTT_ASSERT(node != nullptr, "Invalid pointer to node");
224 return *node;
225 }
226
227 meta_any(const meta_any &other, any elem)
228 : storage{stl::move(elem)},
229 ctx{other.ctx},
230 node{other.node},
231 vtable{other.vtable} {}
232
233public:
235 meta_any() = default;
236
242 : ctx{&area} {}
243
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)...} {}
252
259 template<typename Type>
260 explicit meta_any(const meta_ctx &area, stl::in_place_type_t<Type>, auto &&...args)
261 : storage{stl::in_place_type<Type>, stl::forward<decltype(args)>(args)...},
262 ctx{&area},
263 vtable{&basic_vtable<stl::remove_cvref_t<Type>>} {}
264
269 explicit meta_any(stl::in_place_t, auto *value)
270 : meta_any{locator<meta_ctx>::value_or(), stl::in_place, value} {}
271
277 explicit meta_any(const meta_ctx &area, stl::in_place_t, auto *value)
278 : storage{stl::in_place, value},
279 ctx{&area},
280 vtable{storage ? &basic_vtable<stl::remove_const_t<stl::remove_pointer_t<decltype(value)>>> : nullptr} {
281 }
282
287 meta_any(auto &&value)
288 requires (!stl::same_as<stl::remove_cvref_t<decltype(value)>, meta_any>)
289 : meta_any{locator<meta_ctx>::value_or(), stl::forward<decltype(value)>(value)} {}
290
296 meta_any(const meta_ctx &area, auto &&value)
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)} {}
299
305 meta_any(const meta_ctx &area, const meta_any &other)
306 : storage{other.storage},
307 ctx{&area},
308 node{(ctx == other.ctx) ? other.node : nullptr},
309 vtable{other.vtable} {}
310
316 meta_any(const meta_ctx &area, meta_any &&other)
317 : storage{stl::move(other.storage)},
318 ctx{&area},
319 node{(ctx == other.ctx) ? stl::exchange(other.node, nullptr) : nullptr},
320 vtable{stl::exchange(other.vtable, nullptr)} {}
321
326 meta_any(const meta_any &other)
327 : storage{other.storage},
328 ctx{other.ctx},
329 node{(other.storage && !storage) ? nullptr : other.node},
330 vtable{(other.storage && !storage) ? nullptr : other.vtable} {
331 }
332
337 meta_any(meta_any &&other) noexcept
338 : storage{stl::move(other.storage)},
339 ctx{other.ctx},
340 node{stl::exchange(other.node, nullptr)},
341 vtable{stl::exchange(other.vtable, nullptr)} {}
342
344 ~meta_any() = default;
345
351 meta_any &operator=(const meta_any &other) {
352 if(this != &other) {
353 ctx = other.ctx;
354 storage = other.storage;
355 node = (other.storage && !storage) ? nullptr : other.node;
356 vtable = (other.storage && !storage) ? nullptr : other.vtable;
357 }
358
359 return *this;
360 }
361
367 meta_any &operator=(meta_any &&other) noexcept {
368 storage = stl::move(other.storage);
369 ctx = other.ctx;
370 node = stl::exchange(other.node, nullptr);
371 vtable = stl::exchange(other.vtable, nullptr);
372 return *this;
373 }
374
380 meta_any &operator=(auto &&value)
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));
383 return *this;
384 }
385
390 [[nodiscard]] inline meta_type type() const noexcept;
391
396 inline void type(const meta_type &alias) noexcept;
397
404 meta_any invoke(id_type id, auto &&...args) const;
405
407 meta_any invoke(id_type id, auto &&...args);
408
415 bool set(id_type id, auto &&...args);
416
423 [[nodiscard]] meta_any get(id_type id, auto &&...args) const;
424
426 [[nodiscard]] meta_any get(id_type id, auto &&...args);
427
433 template<typename Type>
434 [[nodiscard]] const Type *try_cast() const {
435 const auto *elem = any_cast<const Type>(&storage);
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()));
437 }
438
440 template<typename Type>
441 [[nodiscard]] Type *try_cast() {
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>>());
443 }
444
450 template<typename Type>
451 [[nodiscard]] stl::remove_const_t<Type> cast() const {
452 auto *const instance = try_cast<stl::remove_reference_t<Type>>();
453 ENTT_ASSERT(instance, "Invalid instance");
454 return static_cast<Type>(*instance);
455 }
456
458 template<typename Type>
459 [[nodiscard]] stl::remove_const_t<Type> cast() {
460 // forces const on non-reference types to make them work also with wrappers for const references
461 auto *const instance = try_cast<stl::remove_reference_t<const Type>>();
462 ENTT_ASSERT(instance, "Invalid instance");
463 return static_cast<Type>(*instance);
464 }
465
471 [[nodiscard]] meta_any allow_cast(const meta_type &type) const;
472
478 [[nodiscard]] bool allow_cast(const meta_type &type);
479
485 template<typename Type>
486 [[nodiscard]] meta_any allow_cast() const {
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>>()) {
489 return as_ref();
490 } else if(*this) {
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()))};
494 }
495 }
496
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());
500 }
501
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()) {
504 return other;
505 } else if(auto from_base = stl::as_const(other).template allow_cast<Type>(); from_base) {
506 return from_base;
507 }
508 }
509 }
510 }
511 }
512
513 return meta_any{meta_ctx_arg, *ctx};
514 }
515
521 template<typename Type>
522 [[nodiscard]] bool allow_cast() {
523 if constexpr(stl::is_reference_v<Type> && !stl::is_const_v<stl::remove_reference_t<Type>>) {
524 return allow_cast<const stl::remove_reference_t<Type> &>() && (storage.policy() != any_policy::cref);
525 } else {
526 if(storage.has_value<stl::remove_cvref_t<Type>>()) {
527 return true;
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);
531 }
532
533 return true;
534 }
535
536 return false;
537 }
538 }
539
541 template<typename Type>
542 void emplace(auto &&...args) {
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;
546 }
547
549 bool assign(const meta_any &other);
550
552 bool assign(meta_any &&other);
553
555 void reset() {
556 storage.reset();
557 node = nullptr;
558 vtable = nullptr;
559 }
560
567 if(*this) { vtable(internal::meta_traits::is_sequence_container, *this, &proxy); }
568 return proxy;
569 }
570
572 [[nodiscard]] meta_sequence_container as_sequence_container() const noexcept {
574 if(*this) { vtable(internal::meta_traits::is_sequence_container, as_ref(), &proxy); }
575 return proxy;
576 }
577
584 if(*this) { vtable(internal::meta_traits::is_associative_container, *this, &proxy); }
585 return proxy;
586 }
587
591 if(*this) { vtable(internal::meta_traits::is_associative_container, as_ref(), &proxy); }
592 return proxy;
593 }
594
600 [[nodiscard]] meta_any operator*() noexcept {
601 meta_any ret{meta_ctx_arg, *ctx};
602 if(*this) { vtable(internal::meta_traits::is_pointer, *this, &ret); }
603 return ret;
604 }
605
607 [[nodiscard]] meta_any operator*() const noexcept {
608 meta_any ret{meta_ctx_arg, *ctx};
609 if(*this) { vtable(internal::meta_traits::is_pointer, as_ref(), &ret); }
610 return ret;
611 }
612
614 [[nodiscard]] explicit operator bool() const noexcept {
615 return !(vtable == nullptr);
616 }
617
619 [[nodiscard]] bool operator==(const meta_any &other) const noexcept {
620 return (ctx == other.ctx) && (!*this == !other) && (storage == other.storage);
621 }
622
624 [[nodiscard]] meta_any as_ref() noexcept {
625 return meta_any{*this, storage.as_ref()};
626 }
627
629 [[nodiscard]] meta_any as_ref() const noexcept {
630 return meta_any{*this, storage.as_ref()};
631 }
632
637 [[nodiscard]] const any &base() const noexcept {
638 return storage;
639 }
640
645 [[nodiscard]] const meta_ctx &context() const noexcept {
646 return *ctx;
647 }
648
649private:
650 any storage{};
651 const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
652 mutable const internal::meta_type_node *node{};
653 vtable_type *vtable{};
654};
655
662[[nodiscard]] meta_any forward_as_meta(const meta_ctx &ctx, auto &&value) {
663 return meta_any{ctx, stl::in_place_type<decltype(value)>, stl::forward<decltype(value)>(value)};
664}
665
671[[nodiscard]] meta_any forward_as_meta(auto &&value) {
672 return forward_as_meta(locator<meta_ctx>::value_or(), stl::forward<decltype(value)>(value));
673}
674
676class meta_handle {
677 meta_handle(int, auto &value, auto &&...args)
678 requires stl::same_as<stl::remove_cvref_t<decltype(value)>, meta_any>
679 : any{stl::forward<decltype(args)>(args)..., value.as_ref()} {}
680
681 meta_handle(char, auto &value, auto &&...args)
682 : any{stl::forward<decltype(args)>(args)..., stl::in_place_type<decltype(value)>, value} {}
683
684public:
686 meta_handle() = default;
687
693 meta_handle(const meta_ctx &ctx, auto &value)
694 requires (!stl::same_as<stl::remove_cvref_t<decltype(value)>, meta_handle>)
695 : meta_handle{0, value, ctx} {}
696
701 meta_handle(auto &value)
702 requires (!stl::same_as<stl::remove_cvref_t<decltype(value)>, meta_handle>)
703 : meta_handle{0, value} {}
704
710 meta_handle(const meta_ctx &area, meta_handle &&other)
711 : any{area, stl::move(other.any)} {}
712
714 meta_handle(const meta_handle &) = delete;
715
717 meta_handle(meta_handle &&) = default;
718
720 ~meta_handle() = default;
721
726 meta_handle &operator=(const meta_handle &) = delete;
727
732 meta_handle &operator=(meta_handle &&) = default;
733
738 [[nodiscard]] explicit operator bool() const noexcept {
739 return static_cast<bool>(any);
740 }
741
746 [[nodiscard]] meta_any *operator->() {
747 return &any;
748 }
749
750private:
751 meta_any any{};
752};
753
757 meta_custom() noexcept = default;
758
763 meta_custom(const internal::meta_custom_node &curr) noexcept
764 : node{&curr} {}
765
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;
773 }
774
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());
783 }
784
785private:
786 const internal::meta_custom_node *node{};
787};
788
793template<typename Type>
794struct meta_object: protected internal::basic_meta_object<Type> {
796 using node_type = Type;
798 using size_type = stl::size_t;
799
801 meta_object() noexcept = default;
802
808 meta_object(const meta_ctx &area, const node_type &curr) noexcept
809 : internal::basic_meta_object<Type>{&curr, &area} {
810 }
811
816 [[nodiscard]] explicit operator bool() const noexcept {
817 return (this->node != nullptr);
818 }
819
825 [[nodiscard]] bool operator==(const meta_object &other) const noexcept {
826 return (this->ctx == other.ctx) && (this->node == other.node);
827 }
828};
829
831struct meta_data: meta_object<internal::meta_data_node> {
833
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};
840 }
841
846 [[nodiscard]] size_type set_arity() const noexcept {
847 return node_or_assert().set_arity;
848 }
849
854 [[nodiscard]] size_type get_arity() const noexcept {
855 return node_or_assert().get_arity;
856 }
857
862 [[nodiscard]] bool is_const() const noexcept {
863 return !!(node_or_assert().traits & internal::meta_traits::is_const);
864 }
865
870 [[nodiscard]] bool is_static() const noexcept {
871 return !!(node_or_assert().traits & internal::meta_traits::is_static);
872 }
873
875 [[nodiscard]] inline meta_type type() const noexcept;
876
884 template<typename Instance = meta_handle>
885 // NOLINTNEXTLINE(modernize-use-nodiscard)
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());
888 }
889
897 template<typename Instance = meta_handle>
898 [[nodiscard]] meta_any get(Instance &&instance, auto &&...args) const {
899 return (sizeof...(args) >= get_arity()) ? node_or_assert().get(meta_handle{*ctx, stl::forward<Instance>(instance)}, stl::array<meta_any, sizeof...(args)>{meta_any{*ctx, stl::forward<decltype(args)>(args)}...}.data()) : meta_any{meta_ctx_arg, *ctx};
900 }
901
907 [[nodiscard]] inline meta_type set_arg(size_type index) const noexcept;
908
914 [[nodiscard]] inline meta_type get_arg(size_type index) const noexcept;
915
921 template<typename Type>
922 [[nodiscard]] Type traits() const noexcept {
923 return internal::meta_to_user_traits<Type>(node_or_assert().traits);
924 }
925
930 [[nodiscard]] meta_custom custom() const noexcept {
931 return {node_or_assert().custom};
932 }
933};
934
936struct meta_func: meta_object<internal::meta_func_node> {
938
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};
945 }
946
951 [[nodiscard]] size_type arity() const noexcept {
952 return node_or_assert().arity;
953 }
954
959 [[nodiscard]] bool is_const() const noexcept {
960 return !!(node_or_assert().traits & internal::meta_traits::is_const);
961 }
962
967 [[nodiscard]] bool is_static() const noexcept {
968 return !!(node_or_assert().traits & internal::meta_traits::is_static);
969 }
970
975 [[nodiscard]] inline meta_type ret() const noexcept;
976
982 [[nodiscard]] inline meta_type arg(size_type index) const noexcept;
983
991 template<typename Instance = meta_handle>
992 // NOLINTNEXTLINE(modernize-use-nodiscard)
993 meta_any invoke(Instance &&instance, auto &&...args) const {
994 return (sizeof...(args) == arity()) ? node_or_assert().invoke(meta_handle{*ctx, stl::forward<Instance>(instance)}, stl::array<meta_any, sizeof...(args)>{meta_any{*ctx, stl::forward<decltype(args)>(args)}...}.data()) : meta_any{meta_ctx_arg, *ctx};
995 }
996
998 template<typename Type>
999 [[nodiscard]] Type traits() const noexcept {
1000 return internal::meta_to_user_traits<Type>(node_or_assert().traits);
1001 }
1002
1004 [[nodiscard]] meta_custom custom() const noexcept {
1005 return {node_or_assert().custom};
1006 }
1007
1012 [[nodiscard]] meta_func next() const {
1013 return (node_or_assert().next != nullptr) ? meta_func{*ctx, *node_or_assert().next} : meta_func{};
1014 }
1015};
1016
1018struct meta_base: meta_object<internal::meta_base_node> {
1020
1022 [[nodiscard]] inline meta_type type() const noexcept;
1023};
1024
1027 friend class meta_any;
1028
1029 [[nodiscard]] const auto &fetch_node() const {
1030 return (node == nullptr) ? internal::resolve<void>(internal::meta_context::from(*ctx)) : *node;
1031 }
1032
1033 [[nodiscard]] auto lookup(meta_handle *const args, const auto sz, [[maybe_unused]] bool constness, auto next) const {
1034 decltype(next()) candidate = nullptr;
1035 size_type same{};
1036 bool ambiguous{};
1037
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)) {
1041 continue;
1042 }
1043 }
1044
1045 if(curr->arity == sz) {
1046 size_type match{};
1047 size_type pos{};
1048
1049 // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and stl::span)
1050 for(; pos < sz; ++pos) {
1051 const auto other = curr->arg(*ctx, pos);
1052 const auto type = args[pos]->type();
1053
1054 if(const auto &info = other.info(); info == type.info()) {
1055 ++match;
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())))) {
1057 break;
1058 }
1059 }
1060 // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1061
1062 if(pos == sz) {
1063 if(!candidate || match > same) {
1064 candidate = curr;
1065 same = match;
1066 ambiguous = false;
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;
1071 ambiguous = false;
1072 continue;
1073 }
1074 }
1075
1076 ambiguous = true;
1077 }
1078 }
1079 }
1080 }
1081
1082 return ambiguous ? nullptr : candidate;
1083 }
1084
1085public:
1087 using size_type = internal::meta_type_node::size_type;
1088
1090 meta_type() noexcept = default;
1091
1097 meta_type(const meta_ctx &area, const internal::meta_type_node &curr) noexcept
1098 : node{&curr},
1099 ctx{&area} {}
1100
1105 [[nodiscard]] const type_info &info() const noexcept {
1106 return *fetch_node().info;
1107 }
1108
1113 [[nodiscard]] id_type alias() const noexcept {
1114 return fetch_node().alias;
1115 }
1116
1121 [[nodiscard]] stl::string_view name() const noexcept {
1122 return (fetch_node().name == nullptr) ? stl::string_view{} : stl::string_view{fetch_node().name};
1123 }
1124
1129 [[nodiscard]] size_type size_of() const noexcept {
1130 return fetch_node().size_of;
1131 }
1132
1138 [[nodiscard]] bool is_arithmetic() const noexcept {
1139 return !!(fetch_node().traits & internal::meta_traits::is_arithmetic);
1140 }
1141
1146 [[nodiscard]] bool is_integral() const noexcept {
1147 return !!(fetch_node().traits & internal::meta_traits::is_integral);
1148 }
1149
1154 [[nodiscard]] bool is_signed() const noexcept {
1155 return !!(fetch_node().traits & internal::meta_traits::is_signed);
1156 }
1157
1162 [[nodiscard]] bool is_array() const noexcept {
1163 return !!(fetch_node().traits & internal::meta_traits::is_array);
1164 }
1165
1170 [[nodiscard]] bool is_enum() const noexcept {
1171 return !!(fetch_node().traits & internal::meta_traits::is_enum);
1172 }
1173
1178 [[nodiscard]] bool is_class() const noexcept {
1179 return !!(fetch_node().traits & internal::meta_traits::is_class);
1180 }
1181
1186 [[nodiscard]] bool is_pointer() const noexcept {
1187 return !!(fetch_node().traits & internal::meta_traits::is_pointer);
1188 }
1189
1195 [[nodiscard]] meta_type remove_pointer() const noexcept {
1196 return meta_type{*ctx, fetch_node().remove_pointer(internal::meta_context::from(*ctx))};
1197 }
1198
1203 [[nodiscard]] bool is_pointer_like() const noexcept {
1204 return !!(fetch_node().traits & internal::meta_traits::is_pointer_like);
1205 }
1206
1211 [[nodiscard]] bool is_sequence_container() const noexcept {
1212 return !!(fetch_node().traits & internal::meta_traits::is_sequence_container);
1213 }
1214
1219 [[nodiscard]] bool is_associative_container() const noexcept {
1220 return !!(fetch_node().traits & internal::meta_traits::is_associative_container);
1221 }
1222
1227 [[nodiscard]] bool is_template_specialization() const noexcept {
1228 return (fetch_node().templ.arity != 0u);
1229 }
1230
1235 [[nodiscard]] size_type template_arity() const noexcept {
1236 return fetch_node().templ.arity;
1237 }
1238
1243 [[nodiscard]] meta_type template_type() const noexcept {
1244 return (fetch_node().templ.resolve != nullptr) ? meta_type{*ctx, fetch_node().templ.resolve(internal::meta_context::from(*ctx))} : meta_type{};
1245 }
1246
1252 [[nodiscard]] meta_type template_arg(const size_type index) const noexcept {
1253 return index < template_arity() ? meta_type{*ctx, fetch_node().templ.arg(internal::meta_context::from(*ctx), index)} : meta_type{};
1254 }
1255
1261 [[nodiscard]] bool can_cast(const meta_type &other) const noexcept {
1262 // casting this is UB in all cases but we aren't going to use the resulting pointer, so...
1263 return other && ((*this == other) || (internal::try_cast(internal::meta_context::from(*ctx), fetch_node(), other.fetch_node().info->hash(), this) != nullptr));
1264 }
1265
1271 [[nodiscard]] bool can_convert(const meta_type &other) const noexcept {
1272 if(const auto &to = other.info().hash(); (info().hash() == to) || ((fetch_node().conversion_helper != nullptr) && (other.is_arithmetic() || other.is_enum()))) {
1273 return true;
1274 } else if(const auto &from = fetch_node(); from.details) {
1275 if(const auto *elem = internal::find_member(from.details->conv, to); elem != nullptr) {
1276 return true;
1277 }
1278
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)) {
1281 return true;
1282 }
1283 }
1284 }
1285
1286 return false;
1287 }
1288
1293 [[nodiscard]] meta_range<meta_base, decltype(internal::meta_type_descriptor::base)::const_iterator> base() const noexcept {
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{};
1296 }
1297
1302 [[nodiscard]] meta_range<meta_data, decltype(internal::meta_type_descriptor::data)::const_iterator> data() const noexcept {
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{};
1305 }
1306
1313 [[nodiscard]] meta_data data(const id_type id, const bool recursive = true) const {
1314 const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), fetch_node(), id, recursive);
1315 return (elem != nullptr) ? meta_data{*ctx, *elem} : meta_data{};
1316 }
1317
1322 [[nodiscard]] meta_range<meta_func, decltype(internal::meta_type_descriptor::func)::const_iterator> func() const noexcept {
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{};
1325 }
1326
1333 [[nodiscard]] meta_func func(const id_type id, const bool recursive = true) const {
1334 const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), fetch_node(), id, recursive);
1335 return (elem != nullptr) ? meta_func{*ctx, *elem} : meta_func{};
1336 }
1337
1343 [[nodiscard]] meta_any construct(auto &&...args) const {
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());
1347 }
1348 }
1349
1350 if(const auto &ref = fetch_node(); (sizeof...(args) == 0u) && (ref.default_constructor != nullptr)) {
1351 return ref.default_constructor(*ctx);
1352 }
1353
1354 return meta_any{meta_ctx_arg, *ctx};
1355 }
1356
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};
1365 }
1366
1372 [[nodiscard]] meta_any from_void(const void *elem) const {
1373 return ((elem != nullptr) && (fetch_node().from_void != nullptr)) ? fetch_node().from_void(*ctx, nullptr, elem) : meta_any{meta_ctx_arg, *ctx};
1374 }
1375
1384 template<typename Instance = meta_handle>
1385 // NOLINTNEXTLINE(modernize-use-nodiscard)
1386 meta_any invoke(const id_type id, Instance &&instance, auto &&...args) const {
1387 meta_handle wrapped{*ctx, stl::forward<Instance>(instance)};
1388
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());
1393 }
1394 }
1395 }
1396
1397 for(auto &&curr: base()) {
1398 if(auto elem = curr.second.type().invoke(id, *wrapped.operator->(), stl::forward<decltype(args)>(args)...); elem) {
1399 return elem;
1400 }
1401 }
1402
1403 return meta_any{meta_ctx_arg, *ctx};
1404 }
1405
1414 template<typename Instance = meta_handle>
1415 // NOLINTNEXTLINE(modernize-use-nodiscard)
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)...);
1419 }
1420
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};
1433 }
1434
1436 template<typename Type>
1437 [[nodiscard]] Type traits() const noexcept {
1438 return internal::meta_to_user_traits<Type>(fetch_node().traits);
1439 }
1440
1442 [[nodiscard]] meta_custom custom() const noexcept {
1443 return fetch_node().custom;
1444 }
1445
1447 [[nodiscard]] explicit operator bool() const noexcept {
1448 return (node != nullptr);
1449 }
1450
1452 [[nodiscard]] bool operator==(const meta_type &other) const noexcept {
1453 return (ctx == other.ctx) && (fetch_node().alias == other.fetch_node().alias);
1454 }
1455
1456private:
1457 mutable const internal::meta_type_node *node{};
1458 const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
1459};
1460
1461[[nodiscard]] inline meta_type meta_any::type() const noexcept {
1462 return *this ? meta_type{*ctx, fetch_node()} : meta_type{};
1463}
1464
1465inline void meta_any::type(const meta_type &alias) noexcept {
1466 ENTT_ASSERT(storage.info() == alias.info(), "Unexpected type");
1467 node = alias.node;
1468 ctx = alias.ctx;
1469}
1470
1471// NOLINTNEXTLINE(modernize-use-nodiscard)
1472meta_any meta_any::invoke(const id_type id, auto &&...args) const {
1473 return type().invoke(id, *this, stl::forward<decltype(args)>(args)...);
1474}
1475
1476meta_any meta_any::invoke(const id_type id, auto &&...args) {
1477 return type().invoke(id, *this, stl::forward<decltype(args)>(args)...);
1478}
1479
1480bool meta_any::set(const id_type id, auto &&...args) {
1481 return type().set(id, *this, stl::forward<decltype(args)>(args)...);
1482}
1483
1484[[nodiscard]] inline meta_any meta_any::get(const id_type id, auto &&...args) const {
1485 return type().get(id, *this, stl::forward<decltype(args)>(args)...);
1486}
1487
1488[[nodiscard]] inline meta_any meta_any::get(const id_type id, auto &&...args) {
1489 return type().get(id, *this, stl::forward<decltype(args)>(args)...);
1490}
1491
1492[[nodiscard]] inline meta_any meta_any::allow_cast(const meta_type &type) const {
1493 if(storage.has_value(type.info())) {
1494 return as_ref();
1495 } else if(*this) {
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);
1500 return other;
1501 }
1502
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());
1506 }
1507
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()) {
1510 return other;
1511 } else if(auto from_base = stl::as_const(other).allow_cast(type); from_base) {
1512 return from_base;
1513 }
1514 }
1515 }
1516 }
1517
1518 return meta_any{meta_ctx_arg, *ctx};
1519}
1520
1521[[nodiscard]] inline bool meta_any::allow_cast(const meta_type &type) {
1522 if(storage.has_value(type.info())) {
1523 return true;
1524 } else if(auto other = stl::as_const(*this).allow_cast(type); other) {
1525 if(other.storage.owner()) {
1526 stl::swap(*this, other);
1527 }
1528
1529 return true;
1530 }
1531
1532 return false;
1533}
1534
1535inline bool meta_any::assign(const meta_any &other) {
1536 if(!storage.assign(other.storage)) {
1537 auto value = other.allow_cast(type());
1538 return storage.assign(value.storage);
1539 }
1540
1541 return true;
1542}
1543
1544inline bool meta_any::assign(meta_any &&other) {
1545 return storage.assign(stl::move(other.storage)) || storage.assign(stl::as_const(other).allow_cast(type()).storage);
1546}
1547
1548[[nodiscard]] inline meta_type meta_data::type() const noexcept {
1549 return meta_type{*ctx, node_or_assert().type(internal::meta_context::from(*ctx))};
1550}
1551
1552[[nodiscard]] inline meta_type meta_data::set_arg(const size_type index) const noexcept {
1553 return index < set_arity() ? node_or_assert().set_arg(*ctx, index) : meta_type{};
1554}
1555
1556[[nodiscard]] inline meta_type meta_data::get_arg(const size_type index) const noexcept {
1557 return index < get_arity() ? node_or_assert().get_arg(*ctx, index) : meta_type{};
1558}
1559
1560[[nodiscard]] inline meta_type meta_func::ret() const noexcept {
1561 return meta_type{*ctx, node_or_assert().ret(internal::meta_context::from(*ctx))};
1562}
1563
1564[[nodiscard]] inline meta_type meta_func::arg(const size_type index) const noexcept {
1565 return index < arity() ? node_or_assert().arg(*ctx, index) : meta_type{};
1566}
1567
1568[[nodiscard]] inline meta_type meta_base::type() const noexcept {
1569 return meta_type{*ctx, node_or_assert().type(internal::meta_context::from(*ctx))};
1570}
1571
1573class meta_sequence_container::meta_iterator final {
1574 using vtable_type = void(const void *, const stl::ptrdiff_t, meta_any *);
1575
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);
1580 }
1581
1582public:
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;
1589
1590 meta_iterator() = default;
1591
1592 meta_iterator(const meta_ctx &area, stl::bidirectional_iterator auto iter) noexcept
1593 : ctx{&area},
1594 vtable{&basic_vtable<decltype(iter)>},
1595 handle{iter} {}
1596
1597 meta_iterator &operator++() noexcept {
1598 return vtable(handle.data(), 1, nullptr), *this;
1599 }
1600
1601 meta_iterator operator++(int value) noexcept {
1602 meta_iterator orig = *this;
1603 vtable(handle.data(), ++value, nullptr);
1604 return orig;
1605 }
1606
1607 meta_iterator &operator--() noexcept {
1608 return vtable(handle.data(), -1, nullptr), *this;
1609 }
1610
1611 meta_iterator operator--(int value) noexcept {
1612 meta_iterator orig = *this;
1613 vtable(handle.data(), --value, nullptr);
1614 return orig;
1615 }
1616
1617 [[nodiscard]] reference operator*() const {
1618 reference other{meta_ctx_arg, *ctx};
1619 vtable(handle.data(), 0, &other);
1620 return other;
1621 }
1622
1623 [[nodiscard]] pointer operator->() const {
1624 return operator*();
1625 }
1626
1627 [[nodiscard]] explicit operator bool() const noexcept {
1628 return (vtable != nullptr);
1629 }
1630
1631 [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
1632 return handle == other.handle;
1633 }
1634
1635 [[nodiscard]] const any &base() const noexcept {
1636 return handle;
1637 }
1638
1639private:
1640 const meta_ctx *ctx{};
1641 vtable_type *vtable{};
1642 any handle{};
1643};
1644
1645class meta_associative_container::meta_iterator final {
1646 using vtable_type = void(const void *, stl::pair<meta_any, meta_any> *);
1647
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);
1653 } else {
1654 other->first.emplace<decltype((it->first))>(it->first);
1655 other->second.emplace<decltype((it->second))>(it->second);
1656 }
1657 } else {
1658 ++const_cast<It &>(it);
1659 }
1660 }
1661
1662public:
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;
1669
1670 meta_iterator() = default;
1671
1672 template<bool KeyOnly>
1673 meta_iterator(const meta_ctx &area, stl::bool_constant<KeyOnly>, stl::forward_iterator auto iter) noexcept
1674 : ctx{&area},
1675 vtable{&basic_vtable<KeyOnly, decltype(iter)>},
1676 handle{iter} {}
1677
1678 meta_iterator &operator++() noexcept {
1679 return vtable(handle.data(), nullptr), *this;
1680 }
1681
1682 meta_iterator operator++(int) noexcept {
1683 meta_iterator orig = *this;
1684 vtable(handle.data(), nullptr);
1685 return orig;
1686 }
1687
1688 [[nodiscard]] reference operator*() const {
1689 reference other{{meta_ctx_arg, *ctx}, {meta_ctx_arg, *ctx}};
1690 vtable(handle.data(), &other);
1691 return other;
1692 }
1693
1694 [[nodiscard]] pointer operator->() const {
1695 return operator*();
1696 }
1697
1698 [[nodiscard]] explicit operator bool() const noexcept {
1699 return (vtable != nullptr);
1700 }
1701
1702 [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
1703 return handle == other.handle;
1704 }
1705
1706private:
1707 const meta_ctx *ctx{};
1708 vtable_type *vtable{};
1709 any handle{};
1710};
1711
1713
1718[[nodiscard]] inline meta_type meta_sequence_container::value_type() const noexcept {
1719 return (value_type_node != nullptr) ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1720}
1721
1727 return size_fn(data);
1728}
1729
1736 return !const_only && resize_fn(const_cast<void *>(data), sz);
1737}
1738
1744 return !const_only && clear_fn(const_cast<void *>(data));
1745}
1746
1753 return !const_only && reserve_fn(const_cast<void *>(data), sz);
1754}
1755
1761 return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, false);
1762}
1763
1769 return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, true);
1770}
1771
1779 // this abomination is necessary because only on macos value_type and const_reference are different types for stl::vector<bool>
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);
1783 }
1784
1785 return iterator{};
1786}
1787
1794 return const_only ? iterator{} : erase_fn(*ctx, const_cast<void *>(data), it);
1795}
1796
1803 auto it = begin();
1804 it.operator++(static_cast<int>(pos) - 1);
1805 return *it;
1806}
1807
1812[[nodiscard]] inline meta_sequence_container::operator bool() const noexcept {
1813 return (data != nullptr);
1814}
1815
1820[[nodiscard]] inline meta_type meta_associative_container::key_type() const noexcept {
1821 return (key_type_node != nullptr) ? meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1822}
1823
1828[[nodiscard]] inline meta_type meta_associative_container::mapped_type() const noexcept {
1829 return (mapped_type_node != nullptr) ? meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1830}
1831
1833[[nodiscard]] inline meta_type meta_associative_container::value_type() const noexcept {
1834 return (value_type_node != nullptr) ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1835}
1836
1839 return size_fn(data);
1840}
1841
1844 return !const_only && clear_fn(const_cast<void *>(data));
1845}
1846
1849 return !const_only && reserve_fn(const_cast<void *>(data), sz);
1850}
1851
1854 return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, false);
1855}
1856
1859 return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, true);
1860}
1861
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());
1872}
1873
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;
1881}
1882
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{};
1890}
1891
1896[[nodiscard]] inline meta_associative_container::operator bool() const noexcept {
1897 return (data != nullptr);
1898}
1899
1900} // namespace entt
1901
1902#endif
const void * data() const noexcept
Returns an opaque pointer to the contained instance.
Definition any.hpp:362
any_policy policy() const noexcept
Returns the current mode of an any object.
Definition any.hpp:525
Service locator, nothing more.
Definition locator.hpp:28
static Service & value_or(Args &&...args)
Returns a service if available or sets it from a fallback type.
Definition locator.hpp:90
Opaque wrapper for values of any type.
Definition meta.hpp:176
bool assign(const meta_any &other)
Assigns a value to the contained object without replacing it.
Definition meta.hpp:1535
meta_any & operator=(const meta_any &other)
Copy assignment operator.
Definition meta.hpp:351
meta_associative_container as_associative_container() noexcept
Returns an associative container proxy.
Definition meta.hpp:582
void emplace(auto &&...args)
Replaces the contained object by creating a new instance directly.
Definition meta.hpp:542
meta_type type() const noexcept
Returns the meta type associated with the contained instance.
Definition meta.hpp:1461
meta_any(const meta_ctx &area, const meta_any &other)
Context aware copy constructor.
Definition meta.hpp:305
meta_any()=default
bool set(id_type id, auto &&...args)
Sets the value of a given variable.
Definition meta.hpp:1480
~meta_any()=default
Default destructor.
meta_any(meta_any &&other) noexcept
Move constructor.
Definition meta.hpp:337
meta_any as_ref() noexcept
Aliasing constructor.
Definition meta.hpp:624
const Type * try_cast() const
Tries to cast an instance to a given type.
Definition meta.hpp:434
meta_any invoke(id_type id, auto &&...args) const
Invokes the underlying function, if possible.
Definition meta.hpp:1472
meta_any(const meta_ctx &area, meta_any &&other)
Context aware move constructor.
Definition meta.hpp:316
stl::remove_const_t< Type > cast()
Tries to cast an instance to a given type.
Definition meta.hpp:459
meta_sequence_container as_sequence_container() noexcept
Returns a sequence container proxy.
Definition meta.hpp:565
Type * try_cast()
Tries to cast an instance to a given type.
Definition meta.hpp:441
meta_associative_container as_associative_container() const noexcept
Returns an associative container proxy.
Definition meta.hpp:589
meta_any(stl::in_place_t, auto *value)
Constructs a wrapper taking ownership of the passed object.
Definition meta.hpp:269
meta_any operator*() const noexcept
Indirection operator for dereferencing opaque objects.
Definition meta.hpp:607
meta_any allow_cast(const meta_type &type) const
Converts an object in such a way that a given cast becomes viable.
Definition meta.hpp:1492
meta_any(const meta_ctx &area, auto &&value)
Constructs a wrapper from a given value.
Definition meta.hpp:296
meta_any operator*() noexcept
Indirection operator for dereferencing opaque objects.
Definition meta.hpp:600
const any & base() const noexcept
Returns the underlying storage.
Definition meta.hpp:637
meta_any as_ref() const noexcept
Aliasing constructor.
Definition meta.hpp:629
meta_any allow_cast() const
Converts an object in such a way that a given cast becomes viable.
Definition meta.hpp:486
meta_any(meta_ctx_arg_t, const meta_ctx &area)
Context aware constructor.
Definition meta.hpp:241
meta_any & operator=(auto &&value)
Value assignment operator.
Definition meta.hpp:380
meta_any(const meta_any &other)
Copy constructor.
Definition meta.hpp:326
stl::remove_const_t< Type > cast() const
Tries to cast an instance to a given type.
Definition meta.hpp:451
meta_any(const meta_ctx &area, stl::in_place_t, auto *value)
Constructs a wrapper taking ownership of the passed object.
Definition meta.hpp:277
void reset()
Destroys contained object.
Definition meta.hpp:555
meta_any(stl::in_place_type_t< Type >, auto &&...args)
Constructs a wrapper by directly initializing the new object.
Definition meta.hpp:250
meta_any(auto &&value)
Constructs a wrapper from a given value.
Definition meta.hpp:287
meta_sequence_container as_sequence_container() const noexcept
Returns a sequence container proxy.
Definition meta.hpp:572
bool operator==(const meta_any &other) const noexcept
Checks if two wrappers differ in their content.
Definition meta.hpp:619
meta_any(const meta_ctx &area, stl::in_place_type_t< Type >, auto &&...args)
Constructs a wrapper by directly initializing the new object.
Definition meta.hpp:260
meta_any get(id_type id, auto &&...args) const
Gets the value of a given variable.
Definition meta.hpp:1484
bool allow_cast()
Converts an object in such a way that a given cast becomes viable.
Definition meta.hpp:522
meta_any & operator=(meta_any &&other) noexcept
Move assignment operator.
Definition meta.hpp:367
const meta_ctx & context() const noexcept
Returns the underlying meta context.
Definition meta.hpp:645
Proxy object for associative containers.
Definition meta.hpp:109
meta_associative_container()=default
Default constructor.
stl::size_t size_type
Unsigned integer type.
Definition meta.hpp:114
size_type erase(meta_any)
Removes the specified element from a container.
Definition meta.hpp:1879
iterator find(meta_any)
Returns an iterator to the element with a given key, if any.
Definition meta.hpp:1888
bool insert(meta_any, meta_any)
Inserts a key-only or key/value element into a container.
Definition meta.hpp:1868
iterator end()
Returns an iterator that is past the last element of a container.
Definition meta.hpp:1858
bool reserve(size_type)
Reserves storage for at least the given number of elements.
Definition meta.hpp:1848
meta_associative_container(const meta_ctx &area, Type &instance) noexcept
Context aware constructor.
Definition meta.hpp:128
iterator begin()
Returns an iterator to the first element of a container.
Definition meta.hpp:1853
size_type size() const noexcept
Returns the size of a container.
Definition meta.hpp:1838
meta_type mapped_type() const noexcept
Returns the meta mapped type of a container.
Definition meta.hpp:1828
meta_iterator iterator
Meta iterator type.
Definition meta.hpp:116
meta_type value_type() const noexcept
Returns the meta value type of a container.
Definition meta.hpp:1833
meta_type key_type() const noexcept
Returns the meta key type of a container.
Definition meta.hpp:1820
bool clear()
Clears the content of a container.
Definition meta.hpp:1843
Opaque pointers to instances of any type.
Definition meta.hpp:676
meta_handle(auto &value)
Creates a handle that points to an unmanaged object.
Definition meta.hpp:701
meta_handle & operator=(const meta_handle &)=delete
Default copy assignment operator, deleted on purpose.
~meta_handle()=default
Default destructor.
meta_handle()=default
meta_handle(const meta_ctx &ctx, auto &value)
Creates a handle that points to an unmanaged object.
Definition meta.hpp:693
meta_handle(meta_handle &&)=default
Default move constructor.
meta_handle(const meta_ctx &area, meta_handle &&other)
Context aware move constructor.
Definition meta.hpp:710
meta_handle(const meta_handle &)=delete
Default copy constructor, deleted on purpose.
meta_handle & operator=(meta_handle &&)=default
Default move assignment operator.
meta_any * operator->()
Access operator for accessing the contained opaque object.
Definition meta.hpp:746
Proxy object for sequence containers.
Definition meta.hpp:48
bool reserve(size_type)
Reserves storage for at least the given number of elements.
Definition meta.hpp:1752
iterator insert(const iterator &, meta_any)
Inserts an element at a specified location of a container.
Definition meta.hpp:1778
meta_type value_type() const noexcept
Returns the meta value type of a container.
Definition meta.hpp:1718
meta_any operator[](size_type)
Returns a reference to the element at a given location of a container.
Definition meta.hpp:1802
meta_sequence_container()=default
Default constructor.
iterator end()
Returns an iterator that is past the last element of a container.
Definition meta.hpp:1768
stl::size_t size_type
Unsigned integer type.
Definition meta.hpp:53
iterator erase(const iterator &)
Removes a given element from a container.
Definition meta.hpp:1793
meta_sequence_container(const meta_ctx &area, Type &instance) noexcept
Context aware constructor.
Definition meta.hpp:67
meta_iterator iterator
Meta iterator type.
Definition meta.hpp:55
bool resize(size_type)
Resizes a container to contain a given number of elements.
Definition meta.hpp:1735
size_type size() const noexcept
Returns the size of a container.
Definition meta.hpp:1726
iterator begin()
Returns an iterator to the first element of a container.
Definition meta.hpp:1760
bool clear()
Clears the content of a container.
Definition meta.hpp:1743
Opaque wrapper for types.
Definition meta.hpp:1026
bool is_pointer() const noexcept
Checks whether a type refers to a pointer or not.
Definition meta.hpp:1186
bool is_arithmetic() const noexcept
Checks whether a type refers to an arithmetic type or not.
Definition meta.hpp:1138
meta_custom custom() const noexcept
Returns user defined data for a given meta object.
Definition meta.hpp:1442
meta_any from_void(void *elem, bool transfer_ownership=false) const
Wraps an opaque element of the underlying type.
Definition meta.hpp:1363
meta_any construct(auto &&...args) const
Definition meta.hpp:1343
meta_type remove_pointer() const noexcept
Provides the type for which the pointer is defined.
Definition meta.hpp:1195
meta_type template_arg(const size_type index) const noexcept
Returns the type of the i-th template argument of a type.
Definition meta.hpp:1252
meta_range< meta_base, decltype(internal::meta_type_descriptor::base)::const_iterator > base() const noexcept
Returns a range to visit registered top-level base meta types.
Definition meta.hpp:1293
bool is_array() const noexcept
Checks whether a type refers to an array type or not.
Definition meta.hpp:1162
meta_data data(const id_type id, const bool recursive=true) const
Lookup utility for meta data (bases are also visited).
Definition meta.hpp:1313
bool is_class() const noexcept
Checks whether a type refers to a class or not.
Definition meta.hpp:1178
meta_any from_void(const void *elem) const
Wraps an opaque element of the underlying type.
Definition meta.hpp:1372
meta_any invoke(const id_type id, Instance &&instance, auto &&...args) const
Definition meta.hpp:1386
bool set(const id_type id, Instance &&instance, auto &&...args) const
Sets the value of a given variable.
Definition meta.hpp:1416
stl::string_view name() const noexcept
Returns the name assigned to a type, if any.
Definition meta.hpp:1121
bool can_convert(const meta_type &other) const noexcept
Checks whether a type supports conversion to another type.
Definition meta.hpp:1271
internal::meta_type_node::size_type size_type
Unsigned integer type.
Definition meta.hpp:1087
bool is_signed() const noexcept
Checks whether a type refers to a signed type or not.
Definition meta.hpp:1154
bool is_enum() const noexcept
Checks whether a type refers to an enum or not.
Definition meta.hpp:1170
bool can_cast(const meta_type &other) const noexcept
Checks if a type supports direct casting to another type.
Definition meta.hpp:1261
meta_type() noexcept=default
Default constructor.
bool operator==(const meta_type &other) const noexcept
Checks if two objects refer to the same type.
Definition meta.hpp:1452
bool is_pointer_like() const noexcept
Checks whether a type is a pointer-like type or not.
Definition meta.hpp:1203
meta_any get(const id_type id, Instance &&instance, auto &&...args) const
Gets the value of a given variable.
Definition meta.hpp:1430
Type traits() const noexcept
Returns all meta traits for a given meta object.
Definition meta.hpp:1437
meta_range< meta_func, decltype(internal::meta_type_descriptor::func)::const_iterator > func() const noexcept
Returns a range to visit registered top-level functions.
Definition meta.hpp:1322
meta_func func(const id_type id, const bool recursive=true) const
Lookup utility for meta functions (bases are also visited).
Definition meta.hpp:1333
meta_range< meta_data, decltype(internal::meta_type_descriptor::data)::const_iterator > data() const noexcept
Returns a range to visit registered top-level meta data.
Definition meta.hpp:1302
bool is_integral() const noexcept
Checks whether a type refers to an integral type or not.
Definition meta.hpp:1146
meta_type template_type() const noexcept
Returns a tag for the class template of the underlying type.
Definition meta.hpp:1243
const type_info & info() const noexcept
Returns the type info object of the underlying type.
Definition meta.hpp:1105
bool is_template_specialization() const noexcept
Checks whether a type refers to a template specialization or not.
Definition meta.hpp:1227
bool is_associative_container() const noexcept
Checks whether a type refers to an associative container or not.
Definition meta.hpp:1219
size_type template_arity() const noexcept
Returns the number of template arguments.
Definition meta.hpp:1235
size_type size_of() const noexcept
Returns the size of the underlying type if known.
Definition meta.hpp:1129
id_type alias() const noexcept
Returns the alias assigned to a type.
Definition meta.hpp:1113
bool is_sequence_container() const noexcept
Checks whether a type refers to a sequence container or not.
Definition meta.hpp:1211
Custom EnTT namespace for the standard template library.
Definition entt.hpp:5
EnTT default namespace.
Definition dense_map.hpp:25
@ in_place
In-place deletion policy.
Definition fwd.hpp:22
basic_handle< registry > handle
Alias declaration for the most common use case.
Definition fwd.hpp:102
basic_any<> any
Alias declaration for the most common use case.
Definition fwd.hpp:32
iterable_adaptor< internal::meta_range_iterator< Type, It > > meta_range
Iterable range to use to iterate all types of meta objects.
Definition range.hpp:115
meta_any forward_as_meta(const meta_ctx &ctx, auto &&value)
Forwards its argument and avoids copies for lvalue references.
Definition meta.hpp:662
constexpr bool is_complete_v
Helper variable template.
constexpr get_t< Type... > get
Variable template for lists of observed elements.
Definition fwd.hpp:168
constexpr meta_ctx_arg_t meta_ctx_arg
Constant of type meta_context_arg_t used to disambiguate calls.
Definition fwd.hpp:39
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.
Definition any.hpp:545
void invoke(Registry &reg, const typename Registry::entity_type entt)
Helper to create a listener that directly invokes a member function.
Definition helper.hpp:108
@ ref
Aliasing mode, non-const reference.
Definition fwd.hpp:19
@ cref
Const aliasing mode, const reference.
Definition fwd.hpp:21
stl::uint32_t id_type
Alias declaration for type identifiers.
Definition fwd.hpp:29
basic_storage< Type > storage
Alias declaration for the most common use case.
Definition fwd.hpp:79
static decltype(auto) dereference(const Type &value)
Uses the default ADL based lookup method to resolve the call.
Opaque wrapper for base types.
Definition meta.hpp:1018
meta_object() noexcept=default
Default constructor.
meta_type type() const noexcept
Returns the meta type associated with the contained instance.
Definition meta.hpp:1568
Disambiguation tag for constructors and the like.
Definition fwd.hpp:36
Opaque meta context type.
Definition context.hpp:30
Opaque wrapper for user defined data of any type.
Definition meta.hpp:755
meta_custom() noexcept=default
Default constructor.
Opaque wrapper for data members.
Definition meta.hpp:831
bool set(Instance &&instance, auto &&...args) const
Sets the value of a given variable.
Definition meta.hpp:886
bool is_const() const noexcept
Indicates whether a data member is constant or not.
Definition meta.hpp:862
size_type get_arity() const noexcept
Returns the number of arguments of a data member's getter.
Definition meta.hpp:854
meta_object() noexcept=default
Default constructor.
meta_type get_arg(size_type index) const noexcept
Returns the type of the i-th argument of a data member's getter.
Definition meta.hpp:1556
meta_type set_arg(size_type index) const noexcept
Returns the type of the i-th argument of a data member's setter.
Definition meta.hpp:1552
stl::string_view name() const noexcept
Returns the name assigned to a data member, if any.
Definition meta.hpp:838
size_type set_arity() const noexcept
Returns the number of arguments of a data member's setter.
Definition meta.hpp:846
meta_custom custom() const noexcept
Returns user defined data for a given meta object.
Definition meta.hpp:930
meta_type type() const noexcept
Returns the meta type associated with the contained instance.
Definition meta.hpp:1548
meta_any get(Instance &&instance, auto &&...args) const
Gets the value of a given variable.
Definition meta.hpp:898
bool is_static() const noexcept
Indicates whether a data member is static or not.
Definition meta.hpp:870
Type traits() const noexcept
Returns all meta traits for a given meta object.
Definition meta.hpp:922
Opaque wrapper for member functions.
Definition meta.hpp:936
bool is_static() const noexcept
Indicates whether a member function is static or not.
Definition meta.hpp:967
meta_object() noexcept=default
Default constructor.
meta_type ret() const noexcept
Returns the return type of a member function.
Definition meta.hpp:1560
Type traits() const noexcept
Returns all meta traits for a given meta object.
Definition meta.hpp:999
meta_any invoke(Instance &&instance, auto &&...args) const
Invokes the underlying function, if possible.
Definition meta.hpp:993
bool is_const() const noexcept
Indicates whether a member function is constant or not.
Definition meta.hpp:959
meta_custom custom() const noexcept
Returns user defined data for a given meta object.
Definition meta.hpp:1004
stl::string_view name() const noexcept
Returns the name assigned to a member function, if any.
Definition meta.hpp:943
meta_func next() const
Returns the next overload of a given function, if any.
Definition meta.hpp:1012
meta_type arg(size_type index) const noexcept
Returns the type of the i-th argument of a member function.
Definition meta.hpp:1564
size_type arity() const noexcept
Returns the number of arguments accepted by a member function.
Definition meta.hpp:951
bool operator==(const meta_object &other) const noexcept
Checks if two objects refer to the same type.
Definition meta.hpp:825
stl::size_t size_type
Unsigned integer type.
Definition meta.hpp:798
Type node_type
Underlying meta node type.
Definition meta.hpp:796
meta_object() noexcept=default
Default constructor.
Traits class template to be specialized to enable support for meta sequence containers.
Implementation specific information about a type.