EnTT 3.16.0
Loading...
Searching...
No Matches
meta.hpp
1#ifndef ENTT_META_META_HPP
2#define ENTT_META_META_HPP
3
4#include <array>
5#include <cstddef>
6#include <iterator>
7#include <memory>
8#include <type_traits>
9#include <utility>
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"
19#include "context.hpp"
20#include "fwd.hpp"
21#include "node.hpp"
22#include "range.hpp"
23#include "type_traits.hpp"
24
25namespace entt {
26
27class meta_any;
28class meta_type;
29
32 class meta_iterator;
33
34public:
36 using size_type = std::size_t;
38 using iterator = meta_iterator;
39
42
49 template<typename Type>
50 meta_sequence_container(const meta_ctx &area, Type &instance) noexcept
51 : ctx{&area},
52 data{&instance},
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_end_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::iter},
60 insert_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::insert},
61 erase_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::erase},
62 const_only{std::is_const_v<Type>} {}
63
64 [[nodiscard]] inline meta_type value_type() const noexcept;
65 [[nodiscard]] inline size_type size() const noexcept;
66 inline bool resize(size_type);
67 inline bool clear();
68 inline bool reserve(size_type);
69 [[nodiscard]] inline iterator begin();
70 [[nodiscard]] inline iterator end();
71 inline iterator insert(const iterator &, meta_any);
72 inline iterator erase(const iterator &);
73 [[nodiscard]] inline meta_any operator[](size_type);
74 [[nodiscard]] inline explicit operator bool() const noexcept;
75
76private:
77 const meta_ctx *ctx{};
78 const void *data{};
79 const internal::meta_type_node &(*value_type_node)(const internal::meta_context &){};
80 const internal::meta_type_node &(*const_reference_node)(const internal::meta_context &){};
81 size_type (*size_fn)(const void *){};
82 bool (*clear_fn)(void *){};
83 bool (*reserve_fn)(void *, const size_type){};
84 bool (*resize_fn)(void *, const size_type){};
85 iterator (*begin_end_fn)(const meta_ctx &, void *, const void *, const bool){};
86 iterator (*insert_fn)(const meta_ctx &, void *, const void *, const void *, const iterator &){};
87 iterator (*erase_fn)(const meta_ctx &, void *, const iterator &){};
88 bool const_only{};
89};
90
93 class meta_iterator;
94
95public:
97 using size_type = std::size_t;
99 using iterator = meta_iterator;
100
103
110 template<typename Type>
111 meta_associative_container(const meta_ctx &area, Type &instance) noexcept
112 : ctx{&area},
113 data{&instance},
114 key_type_node{&internal::resolve<typename Type::key_type>},
115 value_type_node{&internal::resolve<typename Type::value_type>},
116 size_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::size},
117 clear_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::clear},
118 reserve_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::reserve},
119 begin_end_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::iter},
120 insert_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::insert},
121 erase_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::erase},
122 find_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::find},
123 const_only{std::is_const_v<Type>} {
124 if constexpr(!meta_associative_container_traits<std::remove_const_t<Type>>::key_only) {
125 mapped_type_node = &internal::resolve<typename Type::mapped_type>;
126 }
127 }
128
129 [[nodiscard]] inline meta_type key_type() const noexcept;
130 [[nodiscard]] inline meta_type mapped_type() const noexcept;
131 [[nodiscard]] inline meta_type value_type() const noexcept;
132 [[nodiscard]] inline size_type size() const noexcept;
133 inline bool clear();
134 inline bool reserve(size_type);
135 [[nodiscard]] inline iterator begin();
136 [[nodiscard]] inline iterator end();
137 inline bool insert(meta_any, meta_any);
138 inline size_type erase(meta_any);
139 [[nodiscard]] inline iterator find(meta_any);
140 [[nodiscard]] inline explicit operator bool() const noexcept;
141
142private:
143 const meta_ctx *ctx{};
144 const void *data{};
145 const internal::meta_type_node &(*key_type_node)(const internal::meta_context &){};
146 const internal::meta_type_node &(*mapped_type_node)(const internal::meta_context &){};
147 const internal::meta_type_node &(*value_type_node)(const internal::meta_context &){};
148 size_type (*size_fn)(const void *){};
149 bool (*clear_fn)(void *){};
150 bool (*reserve_fn)(void *, const size_type){};
151 iterator (*begin_end_fn)(const meta_ctx &, void *, const void *, const bool){};
152 bool (*insert_fn)(void *, const void *, const void *){};
153 size_type (*erase_fn)(void *, const void *){};
154 iterator (*find_fn)(const meta_ctx &, void *, const void *, const void *){};
155 bool const_only{};
156};
157
159class meta_any {
160 using vtable_type = void(const internal::meta_traits, const meta_any &, const void *);
161
162 template<typename Type>
163 static void basic_vtable(const internal::meta_traits req, const meta_any &value, [[maybe_unused]] const void *other) {
164 static_assert(std::is_same_v<std::remove_const_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
165
166 if(req == internal::meta_traits::is_none) {
167 value.node = &internal::resolve<Type>(internal::meta_context::from(*value.ctx));
168 }
169
170 if constexpr(is_meta_pointer_like_v<Type>) {
171 if(req == internal::meta_traits::is_pointer_like) {
172 if constexpr(std::is_function_v<typename std::pointer_traits<Type>::element_type>) {
173 const_cast<meta_any &>(value).emplace<Type>(*static_cast<const Type *>(other));
174 } else if constexpr(!std::is_void_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) {
175 using in_place_type = decltype(adl_meta_pointer_like<Type>::dereference(std::declval<const Type &>()));
176
177 if constexpr(std::is_constructible_v<bool, Type>) {
178 if(const auto &pointer_like = *static_cast<const Type *>(other); pointer_like) {
179 const_cast<meta_any &>(value).emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(pointer_like));
180 }
181 } else {
182 const_cast<meta_any &>(value).emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(*static_cast<const Type *>(other)));
183 }
184 }
185 }
186 }
187
189 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)) {
190 using container_type = std::conditional_t<is_complete_v<meta_sequence_container_traits<Type>>, meta_sequence_container, meta_associative_container>;
191
192 if(!!(req & internal::meta_traits::is_const) || (value.storage.policy() == any_policy::cref)) {
193 // NOLINTNEXTLINE(bugprone-casting-through-void)
194 *static_cast<container_type *>(const_cast<void *>(other)) = container_type{*value.ctx, any_cast<const Type &>(value.storage)};
195 } else {
196 // NOLINTNEXTLINE(bugprone-casting-through-void)
197 *static_cast<container_type *>(const_cast<void *>(other)) = container_type{*value.ctx, any_cast<Type &>(const_cast<meta_any &>(value).storage)};
198 }
199 }
200 }
201 }
202
203 [[nodiscard]] const auto &fetch_node() const {
204 if(node == nullptr) {
205 ENTT_ASSERT(*this, "Invalid vtable function");
206 vtable(internal::meta_traits::is_none, *this, nullptr);
207 }
208
209 ENTT_ASSERT(node != nullptr, "Invalid pointer to node");
210 return *node;
211 }
212
213 meta_any(const meta_any &other, any elem)
214 : storage{std::move(elem)},
215 ctx{other.ctx},
216 node{other.node},
217 vtable{other.vtable} {}
218
219public:
221 meta_any() = default;
222
228 : ctx{&area} {}
229
236 template<typename Type, typename... Args>
237 explicit meta_any(std::in_place_type_t<Type>, Args &&...args)
238 : meta_any{locator<meta_ctx>::value_or(), std::in_place_type<Type>, std::forward<Args>(args)...} {}
239
247 template<typename Type, typename... Args>
248 explicit meta_any(const meta_ctx &area, std::in_place_type_t<Type>, Args &&...args)
249 : storage{std::in_place_type<Type>, std::forward<Args>(args)...},
250 ctx{&area},
251 vtable{&basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>} {}
252
258 template<typename Type>
259 explicit meta_any(std::in_place_t, Type *value)
260 : meta_any{locator<meta_ctx>::value_or(), std::in_place, value} {}
261
268 template<typename Type>
269 explicit meta_any(const meta_ctx &area, std::in_place_t, Type *value)
270 : storage{std::in_place, value},
271 ctx{&area},
272 vtable{storage ? &basic_vtable<Type> : nullptr} {
273 }
274
280 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
281 meta_any(Type &&value)
282 : meta_any{locator<meta_ctx>::value_or(), std::forward<Type>(value)} {}
283
290 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
291 meta_any(const meta_ctx &area, Type &&value)
292 : meta_any{area, std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
293
299 meta_any(const meta_ctx &area, const meta_any &other)
300 : storage{other.storage},
301 ctx{&area},
302 node{(ctx == other.ctx) ? other.node : nullptr},
303 vtable{other.vtable} {}
304
310 meta_any(const meta_ctx &area, meta_any &&other)
311 : storage{std::move(other.storage)},
312 ctx{&area},
313 node{(ctx == other.ctx) ? std::exchange(other.node, nullptr) : nullptr},
314 vtable{std::exchange(other.vtable, nullptr)} {}
315
320 meta_any(const meta_any &other) = default;
321
326 meta_any(meta_any &&other) noexcept
327 : storage{std::move(other.storage)},
328 ctx{other.ctx},
329 node{std::exchange(other.node, nullptr)},
330 vtable{std::exchange(other.vtable, nullptr)} {}
331
333 ~meta_any() = default;
334
340 meta_any &operator=(const meta_any &other) {
341 if(this != &other) {
342 storage = other.storage;
343 ctx = other.ctx;
344 node = other.node;
345 vtable = other.vtable;
346 }
347
348 return *this;
349 }
350
356 meta_any &operator=(meta_any &&other) noexcept {
357 storage = std::move(other.storage);
358 ctx = other.ctx;
359 node = std::exchange(other.node, nullptr);
360 vtable = std::exchange(other.vtable, nullptr);
361 return *this;
362 }
363
370 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
371 meta_any &operator=(Type &&value) {
372 emplace<std::decay_t<Type>>(std::forward<Type>(value));
373 return *this;
374 }
375
377 [[nodiscard]] inline meta_type type() const noexcept;
378
386 template<typename... Args>
387 meta_any invoke(id_type id, Args &&...args) const;
388
390 template<typename... Args>
391 meta_any invoke(id_type id, Args &&...args);
392
400 template<typename Type>
401 bool set(id_type id, Type &&value);
402
408 [[nodiscard]] meta_any get(id_type id) const;
409
411 [[nodiscard]] meta_any get(id_type id);
412
418 template<typename Type>
419 [[nodiscard]] const Type *try_cast() const {
420 const auto *elem = any_cast<const Type>(&storage);
421 return ((elem != nullptr) || !*this) ? elem : static_cast<const Type *>(internal::try_cast(internal::meta_context::from(*ctx), fetch_node(), type_hash<std::remove_const_t<Type>>::value(), storage.data()));
422 }
423
425 template<typename Type>
426 [[nodiscard]] Type *try_cast() {
427 return ((storage.policy() == any_policy::cref) && !std::is_const_v<Type>) ? nullptr : const_cast<Type *>(std::as_const(*this).try_cast<std::remove_const_t<Type>>());
428 }
429
435 template<typename Type>
436 [[nodiscard]] std::remove_const_t<Type> cast() const {
437 auto *const instance = try_cast<std::remove_reference_t<Type>>();
438 ENTT_ASSERT(instance, "Invalid instance");
439 return static_cast<Type>(*instance);
440 }
441
443 template<typename Type>
444 [[nodiscard]] std::remove_const_t<Type> cast() {
445 // forces const on non-reference types to make them work also with wrappers for const references
446 auto *const instance = try_cast<std::remove_reference_t<const Type>>();
447 ENTT_ASSERT(instance, "Invalid instance");
448 return static_cast<Type>(*instance);
449 }
450
456 [[nodiscard]] meta_any allow_cast(const meta_type &type) const;
457
463 [[nodiscard]] bool allow_cast(const meta_type &type);
464
470 template<typename Type>
471 [[nodiscard]] meta_any allow_cast() const {
472 if constexpr(!std::is_reference_v<Type> || std::is_const_v<std::remove_reference_t<Type>>) {
473 if(storage.has_value<std::remove_const_t<std::remove_reference_t<Type>>>()) {
474 return as_ref();
475 } else if(*this) {
476 if constexpr(std::is_arithmetic_v<std::remove_const_t<std::remove_reference_t<Type>>> || std::is_enum_v<std::remove_const_t<std::remove_reference_t<Type>>>) {
477 if(const auto &from = fetch_node(); from.conversion_helper) {
478 return meta_any{*ctx, static_cast<Type>(from.conversion_helper(nullptr, storage.data()))};
479 }
480 }
481
482 if(const auto &from = fetch_node(); from.details != nullptr) {
483 if(const auto *elem = internal::find_member<&internal::meta_conv_node::type>(from.details->conv, entt::type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()); elem != nullptr) {
484 return elem->conv(*ctx, storage.data());
485 }
486
487 for(auto &&curr: from.details->base) {
488 if(auto other = curr.resolve(internal::meta_context::from(*ctx)).from_void(*ctx, nullptr, curr.cast(storage.data())); curr.type == entt::type_hash<std::remove_const_t<std::remove_reference_t<Type>>>::value()) {
489 return other;
490 } else if(auto from_base = std::as_const(other).template allow_cast<Type>(); from_base) {
491 return from_base;
492 }
493 }
494 }
495 }
496 }
497
498 return meta_any{meta_ctx_arg, *ctx};
499 }
500
506 template<typename Type>
507 [[nodiscard]] bool allow_cast() {
508 if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
509 return allow_cast<const std::remove_reference_t<Type> &>() && (storage.policy() != any_policy::cref);
510 } else {
511 if(storage.has_value<std::remove_const_t<std::remove_reference_t<Type>>>()) {
512 return true;
513 } else if(auto other = std::as_const(*this).allow_cast<std::remove_const_t<std::remove_reference_t<Type>>>(); other) {
514 if(other.storage.owner()) {
515 std::swap(*this, other);
516 }
517
518 return true;
519 }
520
521 return false;
522 }
523 }
524
526 template<typename Type, typename... Args>
527 void emplace(Args &&...args) {
528 storage.emplace<Type>(std::forward<Args>(args)...);
529 auto *prev = std::exchange(vtable, &basic_vtable<std::remove_const_t<std::remove_reference_t<Type>>>);
530 node = (prev == vtable) ? node : nullptr;
531 }
532
534 bool assign(const meta_any &other);
535
537 bool assign(meta_any &&other);
538
540 void reset() {
541 storage.reset();
542 node = nullptr;
543 vtable = nullptr;
544 }
545
552 if(*this) { vtable(internal::meta_traits::is_sequence_container, *this, &proxy); }
553 return proxy;
554 }
555
557 [[nodiscard]] meta_sequence_container as_sequence_container() const noexcept {
559 if(*this) { vtable(internal::meta_traits::is_sequence_container | internal::meta_traits::is_const, *this, &proxy); }
560 return proxy;
561 }
562
569 if(*this) { vtable(internal::meta_traits::is_associative_container, *this, &proxy); }
570 return proxy;
571 }
572
576 if(*this) { vtable(internal::meta_traits::is_associative_container | internal::meta_traits::is_const, *this, &proxy); }
577 return proxy;
578 }
579
585 [[nodiscard]] meta_any operator*() const noexcept {
586 meta_any ret{meta_ctx_arg, *ctx};
587 if(*this) { vtable(internal::meta_traits::is_pointer_like, ret, storage.data()); }
588 return ret;
589 }
590
592 [[nodiscard]] explicit operator bool() const noexcept {
593 return !(vtable == nullptr);
594 }
595
597 [[nodiscard]] bool operator==(const meta_any &other) const noexcept {
598 return (ctx == other.ctx) && (!*this == !other) && (storage == other.storage);
599 }
600
602 [[nodiscard]] bool operator!=(const meta_any &other) const noexcept {
603 return !(*this == other);
604 }
605
607 [[nodiscard]] meta_any as_ref() noexcept {
608 return meta_any{*this, storage.as_ref()};
609 }
610
612 [[nodiscard]] meta_any as_ref() const noexcept {
613 return meta_any{*this, storage.as_ref()};
614 }
615
620 [[nodiscard]] const any &base() const noexcept {
621 return storage;
622 }
623
628 [[nodiscard]] const meta_ctx &context() const noexcept {
629 return *ctx;
630 }
631
632private:
633 any storage{};
634 const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
635 mutable const internal::meta_type_node *node{};
636 vtable_type *vtable{};
637};
638
646template<typename Type>
647[[nodiscard]] meta_any forward_as_meta(const meta_ctx &ctx, Type &&value) {
648 return meta_any{ctx, std::in_place_type<Type &&>, std::forward<Type>(value)};
649}
650
657template<typename Type>
658[[nodiscard]] meta_any forward_as_meta(Type &&value) {
659 return forward_as_meta(locator<meta_ctx>::value_or(), std::forward<Type>(value));
660}
661
663class meta_handle {
664 template<typename Type, typename... Args, typename = std::enable_if_t<std::is_same_v<std::decay_t<Type>, meta_any>>>
665 meta_handle(int, Type &value, Args &&...args)
666 : any{std::forward<Args>(args)..., value.as_ref()} {}
667
668 template<typename Type, typename... Args>
669 meta_handle(char, Type &value, Args &&...args)
670 : any{std::forward<Args>(args)..., std::in_place_type<Type &>, value} {}
671
672public:
674 meta_handle() = default;
675
682 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
683 meta_handle(const meta_ctx &ctx, Type &value)
684 : meta_handle{0, value, ctx} {}
685
691 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
692 meta_handle(Type &value)
693 : meta_handle{0, value} {}
694
700 meta_handle(const meta_ctx &area, meta_handle &&other)
701 : any{area, std::move(other.any)} {}
702
704 meta_handle(const meta_handle &) = delete;
705
707 meta_handle(meta_handle &&) = default;
708
710 ~meta_handle() = default;
711
716 meta_handle &operator=(const meta_handle &) = delete;
717
722 meta_handle &operator=(meta_handle &&) = default;
723
728 [[nodiscard]] explicit operator bool() const noexcept {
729 return static_cast<bool>(any);
730 }
731
736 [[nodiscard]] meta_any *operator->() {
737 return &any;
738 }
739
741 [[deprecated("do not use const handles")]] [[nodiscard]] const meta_any *operator->() const {
742 return &any;
743 }
744
745private:
746 meta_any any{};
747};
748
752 meta_custom() noexcept = default;
753
758 meta_custom(const internal::meta_custom_node &curr) noexcept
759 : node{&curr} {}
760
765 template<typename Type>
766 [[nodiscard]] operator Type *() const noexcept {
767 return ((node != nullptr) && (type_hash<std::remove_const_t<Type>>::value() == node->type)) ? static_cast<Type *>(node->value.get()) : nullptr;
768 }
769
774 template<typename Type>
775 [[nodiscard]] operator Type &() const noexcept {
776 ENTT_ASSERT(static_cast<Type *>(*this) != nullptr, "Invalid type");
777 return *static_cast<Type *>(node->value.get());
778 }
779
780private:
781 const internal::meta_custom_node *node{};
782};
783
786 [[nodiscard]] auto &node_or_assert() const noexcept {
787 ENTT_ASSERT(node != nullptr, "Invalid pointer to node");
788 return *node;
789 }
790
791public:
793 using size_type = typename internal::meta_data_node::size_type;
794
796 meta_data() noexcept = default;
797
803 meta_data(const meta_ctx &area, const internal::meta_data_node &curr) noexcept
804 : node{&curr},
805 ctx{&area} {}
806
811 [[nodiscard]] const char *name() const noexcept {
812 return node_or_assert().name;
813 }
814
819 [[nodiscard]] size_type arity() const noexcept {
820 return node_or_assert().arity;
821 }
822
827 [[nodiscard]] bool is_const() const noexcept {
828 return !!(node_or_assert().traits & internal::meta_traits::is_const);
829 }
830
835 [[nodiscard]] bool is_static() const noexcept {
836 return !!(node_or_assert().traits & internal::meta_traits::is_static);
837 }
838
840 [[nodiscard]] inline meta_type type() const noexcept;
841
850 template<typename Instance = meta_handle, typename Type>
851 // NOLINTNEXTLINE(modernize-use-nodiscard)
852 bool set(Instance &&instance, Type &&value) const {
853 return node_or_assert().set(meta_handle{*ctx, std::forward<Instance>(instance)}, meta_any{*ctx, std::forward<Type>(value)});
854 }
855
862 template<typename Instance = meta_handle>
863 [[nodiscard]] meta_any get(Instance &&instance) const {
864 return node_or_assert().get(meta_handle{*ctx, std::forward<Instance>(instance)});
865 }
866
872 [[nodiscard]] inline meta_type arg(size_type index) const noexcept;
873
879 template<typename Type>
880 [[nodiscard]] Type traits() const noexcept {
881 return internal::meta_to_user_traits<Type>(node_or_assert().traits);
882 }
883
888 [[nodiscard]] meta_custom custom() const noexcept {
889 return {node_or_assert().custom};
890 }
891
896 [[nodiscard]] explicit operator bool() const noexcept {
897 return (node != nullptr);
898 }
899
905 [[nodiscard]] bool operator==(const meta_data &other) const noexcept {
906 return (ctx == other.ctx) && (node == other.node);
907 }
908
909private:
910 const internal::meta_data_node *node{};
911 const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
912};
913
920[[nodiscard]] inline bool operator!=(const meta_data &lhs, const meta_data &rhs) noexcept {
921 return !(lhs == rhs);
922}
923
926 [[nodiscard]] auto &node_or_assert() const noexcept {
927 ENTT_ASSERT(node != nullptr, "Invalid pointer to node");
928 return *node;
929 }
930
931public:
933 using size_type = typename internal::meta_func_node::size_type;
934
936 meta_func() noexcept = default;
937
943 meta_func(const meta_ctx &area, const internal::meta_func_node &curr) noexcept
944 : node{&curr},
945 ctx{&area} {}
946
951 [[nodiscard]] const char *name() const noexcept {
952 return node_or_assert().name;
953 }
954
959 [[nodiscard]] size_type arity() const noexcept {
960 return node_or_assert().arity;
961 }
962
967 [[nodiscard]] bool is_const() const noexcept {
968 return !!(node_or_assert().traits & internal::meta_traits::is_const);
969 }
970
975 [[nodiscard]] bool is_static() const noexcept {
976 return !!(node_or_assert().traits & internal::meta_traits::is_static);
977 }
978
983 [[nodiscard]] inline meta_type ret() const noexcept;
984
990 [[nodiscard]] inline meta_type arg(size_type index) const noexcept;
991
1000 template<typename Instance = meta_handle>
1001 meta_any invoke(Instance &&instance, meta_any *const args, const size_type sz) const {
1002 return (sz == arity()) ? node_or_assert().invoke(meta_handle{*ctx, std::forward<Instance>(instance)}, args) : meta_any{meta_ctx_arg, *ctx};
1003 }
1004
1013 template<typename Instance = meta_handle, typename... Args>
1014 // NOLINTNEXTLINE(modernize-use-nodiscard)
1015 meta_any invoke(Instance &&instance, Args &&...args) const {
1016 return invoke(std::forward<Instance>(instance), std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
1017 }
1018
1020 template<typename Type>
1021 [[nodiscard]] Type traits() const noexcept {
1022 return internal::meta_to_user_traits<Type>(node_or_assert().traits);
1023 }
1024
1026 [[nodiscard]] meta_custom custom() const noexcept {
1027 return {node_or_assert().custom};
1028 }
1029
1034 [[nodiscard]] meta_func next() const {
1035 return (node_or_assert().next != nullptr) ? meta_func{*ctx, *node_or_assert().next} : meta_func{};
1036 }
1037
1039 [[nodiscard]] explicit operator bool() const noexcept {
1040 return (node != nullptr);
1041 }
1042
1044 [[nodiscard]] bool operator==(const meta_func &other) const noexcept {
1045 return (ctx == other.ctx) && (node == other.node);
1046 }
1047
1048private:
1049 const internal::meta_func_node *node{};
1050 const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
1051};
1052
1054[[nodiscard]] inline bool operator!=(const meta_func &lhs, const meta_func &rhs) noexcept {
1055 return !(lhs == rhs);
1056}
1057
1060 [[nodiscard]] const auto &fetch_node() const {
1061 return (node == nullptr) ? internal::resolve<void>(internal::meta_context::from(*ctx)) : *node;
1062 }
1063
1064 template<typename Func>
1065 [[nodiscard]] auto lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, [[maybe_unused]] bool constness, Func next) const {
1066 decltype(next()) candidate = nullptr;
1067 size_type same{};
1068 bool ambiguous{};
1069
1070 for(auto curr = next(); curr; curr = next()) {
1071 if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) {
1072 if(constness && !(curr->traits & internal::meta_traits::is_const)) {
1073 continue;
1074 }
1075 }
1076
1077 if(curr->arity == sz) {
1078 size_type match{};
1079 size_type pos{};
1080
1081 // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span)
1082 for(; pos < sz && args[pos]; ++pos) {
1083 const auto other = curr->arg(*ctx, pos);
1084 const auto type = args[pos].type();
1085
1086 if(const auto &info = other.info(); info == type.info()) {
1087 ++match;
1088 } else if(!(type.fetch_node().conversion_helper && other.fetch_node().conversion_helper) && !(type.fetch_node().details && (internal::find_member<&internal::meta_base_node::type>(type.fetch_node().details->base, info.hash()) || internal::find_member<&internal::meta_conv_node::type>(type.fetch_node().details->conv, info.hash())))) {
1089 break;
1090 }
1091 }
1092 // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1093
1094 if(pos == sz) {
1095 if(!candidate || match > same) {
1096 candidate = curr;
1097 same = match;
1098 ambiguous = false;
1099 } else if(match == same) {
1100 if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) {
1101 if(!!(curr->traits & internal::meta_traits::is_const) != !!(candidate->traits & internal::meta_traits::is_const)) {
1102 candidate = !!(candidate->traits & internal::meta_traits::is_const) ? curr : candidate;
1103 ambiguous = false;
1104 continue;
1105 }
1106 }
1107
1108 ambiguous = true;
1109 }
1110 }
1111 }
1112 }
1113
1114 return ambiguous ? nullptr : candidate;
1115 }
1116
1117public:
1119 using size_type = typename internal::meta_type_node::size_type;
1120
1122 meta_type() noexcept = default;
1123
1129 meta_type(const meta_ctx &area, const internal::meta_type_node &curr) noexcept
1130 : node{&curr},
1131 ctx{&area} {}
1132
1138 meta_type(const meta_ctx &area, const internal::meta_base_node &curr) noexcept
1139 : meta_type{area, curr.resolve(internal::meta_context::from(area))} {}
1140
1145 [[nodiscard]] const type_info &info() const noexcept {
1146 return *fetch_node().info;
1147 }
1148
1153 [[nodiscard]] id_type id() const noexcept {
1154 return fetch_node().id;
1155 }
1156
1161 [[nodiscard]] const char *name() const noexcept {
1162 return fetch_node().name;
1163 }
1164
1169 [[nodiscard]] size_type size_of() const noexcept {
1170 return fetch_node().size_of;
1171 }
1172
1178 [[nodiscard]] bool is_arithmetic() const noexcept {
1179 return !!(fetch_node().traits & internal::meta_traits::is_arithmetic);
1180 }
1181
1186 [[nodiscard]] bool is_integral() const noexcept {
1187 return !!(fetch_node().traits & internal::meta_traits::is_integral);
1188 }
1189
1194 [[nodiscard]] bool is_signed() const noexcept {
1195 return !!(fetch_node().traits & internal::meta_traits::is_signed);
1196 }
1197
1202 [[nodiscard]] bool is_array() const noexcept {
1203 return !!(fetch_node().traits & internal::meta_traits::is_array);
1204 }
1205
1210 [[nodiscard]] bool is_enum() const noexcept {
1211 return !!(fetch_node().traits & internal::meta_traits::is_enum);
1212 }
1213
1218 [[nodiscard]] bool is_class() const noexcept {
1219 return !!(fetch_node().traits & internal::meta_traits::is_class);
1220 }
1221
1226 [[nodiscard]] bool is_pointer() const noexcept {
1227 return !!(fetch_node().traits & internal::meta_traits::is_pointer);
1228 }
1229
1235 [[nodiscard]] meta_type remove_pointer() const noexcept {
1236 return meta_type{*ctx, fetch_node().remove_pointer(internal::meta_context::from(*ctx))};
1237 }
1238
1243 [[nodiscard]] bool is_pointer_like() const noexcept {
1244 return !!(fetch_node().traits & internal::meta_traits::is_pointer_like);
1245 }
1246
1251 [[nodiscard]] bool is_sequence_container() const noexcept {
1252 return !!(fetch_node().traits & internal::meta_traits::is_sequence_container);
1253 }
1254
1259 [[nodiscard]] bool is_associative_container() const noexcept {
1260 return !!(fetch_node().traits & internal::meta_traits::is_associative_container);
1261 }
1262
1267 [[nodiscard]] bool is_template_specialization() const noexcept {
1268 return (fetch_node().templ.arity != 0u);
1269 }
1270
1275 [[nodiscard]] size_type template_arity() const noexcept {
1276 return fetch_node().templ.arity;
1277 }
1278
1283 [[nodiscard]] meta_type template_type() const noexcept {
1284 return (fetch_node().templ.resolve != nullptr) ? meta_type{*ctx, fetch_node().templ.resolve(internal::meta_context::from(*ctx))} : meta_type{};
1285 }
1286
1292 [[nodiscard]] meta_type template_arg(const size_type index) const noexcept {
1293 return index < template_arity() ? meta_type{*ctx, fetch_node().templ.arg(internal::meta_context::from(*ctx), index)} : meta_type{};
1294 }
1295
1301 [[nodiscard]] bool can_cast(const meta_type &other) const noexcept {
1302 // casting this is UB in all cases but we aren't going to use the resulting pointer, so...
1303 return other && ((*this == other) || (internal::try_cast(internal::meta_context::from(*ctx), fetch_node(), other.fetch_node().info->hash(), this) != nullptr));
1304 }
1305
1311 [[nodiscard]] bool can_convert(const meta_type &other) const noexcept {
1312 if(const auto &to = other.info().hash(); (info().hash() == to) || ((fetch_node().conversion_helper != nullptr) && (other.is_arithmetic() || other.is_enum()))) {
1313 return true;
1314 } else if(const auto &from = fetch_node(); from.details) {
1315 if(const auto *elem = internal::find_member<&internal::meta_conv_node::type>(from.details->conv, to); elem != nullptr) {
1316 return true;
1317 }
1318
1319 for(auto &&curr: from.details->base) {
1320 if(curr.type == to || meta_type{*ctx, curr.resolve(internal::meta_context::from(*ctx))}.can_convert(other)) {
1321 return true;
1322 }
1323 }
1324 }
1325
1326 return false;
1327 }
1328
1333 [[nodiscard]] meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator> base() const noexcept {
1334 using range_type = meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator>;
1335 return fetch_node().details ? range_type{{*ctx, fetch_node().details->base.cbegin()}, {*ctx, fetch_node().details->base.cend()}} : range_type{};
1336 }
1337
1342 [[nodiscard]] meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator> data() const noexcept {
1343 using range_type = meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator>;
1344 return fetch_node().details ? range_type{{*ctx, fetch_node().details->data.cbegin()}, {*ctx, fetch_node().details->data.cend()}} : range_type{};
1345 }
1346
1353 [[nodiscard]] meta_data data(const id_type id, const bool recursive = true) const {
1354 const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), fetch_node(), id, recursive);
1355 return (elem != nullptr) ? meta_data{*ctx, *elem} : meta_data{};
1356 }
1357
1362 [[nodiscard]] meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator> func() const noexcept {
1363 using return_type = meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator>;
1364 return fetch_node().details ? return_type{{*ctx, fetch_node().details->func.cbegin()}, {*ctx, fetch_node().details->func.cend()}} : return_type{};
1365 }
1366
1373 [[nodiscard]] meta_func func(const id_type id, const bool recursive = true) const {
1374 const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), fetch_node(), id, recursive);
1375 return (elem != nullptr) ? meta_func{*ctx, *elem} : meta_func{};
1376 }
1377
1384 [[nodiscard]] meta_any construct(meta_any *const args, const size_type sz) const {
1385 if(const auto &ref = fetch_node(); ref.details) {
1386 if(const auto *candidate = lookup(args, sz, false, [first = ref.details->ctor.cbegin(), last = ref.details->ctor.cend()]() mutable { return first == last ? nullptr : &*(first++); }); candidate) {
1387 return candidate->invoke(*ctx, args);
1388 }
1389 }
1390
1391 if(const auto &ref = fetch_node(); (sz == 0u) && (ref.default_constructor != nullptr)) {
1392 return ref.default_constructor(*ctx);
1393 }
1394
1395 return meta_any{meta_ctx_arg, *ctx};
1396 }
1397
1404 template<typename... Args>
1405 [[nodiscard]] meta_any construct(Args &&...args) const {
1406 return construct(std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
1407 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
1408 }
1409
1416 [[nodiscard]] meta_any from_void(void *elem, bool transfer_ownership = false) const {
1417 return ((elem != nullptr) && (fetch_node().from_void != nullptr)) ? fetch_node().from_void(*ctx, elem, transfer_ownership ? elem : nullptr) : meta_any{meta_ctx_arg, *ctx};
1418 }
1419
1425 [[nodiscard]] meta_any from_void(const void *elem) const {
1426 return ((elem != nullptr) && (fetch_node().from_void != nullptr)) ? fetch_node().from_void(*ctx, nullptr, elem) : meta_any{meta_ctx_arg, *ctx};
1427 }
1428
1438 template<typename Instance = meta_handle>
1439 // NOLINTNEXTLINE(modernize-use-nodiscard)
1440 meta_any invoke(const id_type id, Instance &&instance, meta_any *const args, const size_type sz) const {
1441 meta_handle wrapped{*ctx, std::forward<Instance>(instance)};
1442
1443 if(const auto &ref = fetch_node(); ref.details) {
1444 if(auto *elem = internal::find_member<&internal::meta_func_node::id>(ref.details->func, id); elem != nullptr) {
1445 if(const auto *candidate = lookup(args, sz, (wrapped->base().policy() == any_policy::cref), [curr = elem]() mutable { return (curr != nullptr) ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) {
1446 return candidate->invoke(std::move(wrapped), args);
1447 }
1448 }
1449 }
1450
1451 for(auto &&curr: base()) {
1452 if(auto elem = curr.second.invoke(id, *wrapped.operator->(), args, sz); elem) {
1453 return elem;
1454 }
1455 }
1456
1457 return meta_any{meta_ctx_arg, *ctx};
1458 }
1459
1469 template<typename Instance = meta_handle, typename... Args>
1470 // NOLINTNEXTLINE(modernize-use-nodiscard)
1471 meta_any invoke(const id_type id, Instance &&instance, Args &&...args) const {
1472 return invoke(id, std::forward<Instance>(instance), std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
1473 }
1474
1484 template<typename Instance = meta_handle, typename Type>
1485 // NOLINTNEXTLINE(modernize-use-nodiscard)
1486 bool set(const id_type id, Instance &&instance, Type &&value) const {
1487 const auto candidate = data(id);
1488 return candidate && candidate.set(std::forward<Instance>(instance), std::forward<Type>(value));
1489 }
1490
1498 template<typename Instance = meta_handle>
1499 [[nodiscard]] meta_any get(const id_type id, Instance &&instance) const {
1500 const auto candidate = data(id);
1501 return candidate ? candidate.get(std::forward<Instance>(instance)) : meta_any{meta_ctx_arg, *ctx};
1502 }
1503
1505 template<typename Type>
1506 [[nodiscard]] Type traits() const noexcept {
1507 return internal::meta_to_user_traits<Type>(fetch_node().traits);
1508 }
1509
1511 [[nodiscard]] meta_custom custom() const noexcept {
1512 return fetch_node().custom;
1513 }
1514
1516 [[nodiscard]] explicit operator bool() const noexcept {
1517 return (node != nullptr);
1518 }
1519
1521 [[nodiscard]] bool operator==(const meta_type &other) const noexcept {
1522 return (ctx == other.ctx) && (fetch_node().id == other.fetch_node().id);
1523 }
1524
1525private:
1526 mutable const internal::meta_type_node *node{};
1527 const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
1528};
1529
1531[[nodiscard]] inline bool operator!=(const meta_type &lhs, const meta_type &rhs) noexcept {
1532 return !(lhs == rhs);
1533}
1534
1535[[nodiscard]] inline meta_type meta_any::type() const noexcept {
1536 return *this ? meta_type{*ctx, fetch_node()} : meta_type{};
1537}
1538
1539template<typename... Args>
1540// NOLINTNEXTLINE(modernize-use-nodiscard)
1541meta_any meta_any::invoke(const id_type id, Args &&...args) const {
1542 return type().invoke(id, *this, std::forward<Args>(args)...);
1543}
1544
1545template<typename... Args>
1546meta_any meta_any::invoke(const id_type id, Args &&...args) {
1547 return type().invoke(id, *this, std::forward<Args>(args)...);
1548}
1549
1550template<typename Type>
1551bool meta_any::set(const id_type id, Type &&value) {
1552 return type().set(id, *this, std::forward<Type>(value));
1553}
1554
1555[[nodiscard]] inline meta_any meta_any::get(const id_type id) const {
1556 return type().get(id, *this);
1557}
1558
1559[[nodiscard]] inline meta_any meta_any::get(const id_type id) {
1560 return type().get(id, *this);
1561}
1562
1563[[nodiscard]] inline meta_any meta_any::allow_cast(const meta_type &type) const {
1564 if(storage.has_value(type.info())) {
1565 return as_ref();
1566 } else if(*this) {
1567 if(const auto &from = fetch_node(); (from.conversion_helper != nullptr) && (type.is_arithmetic() || type.is_enum())) {
1568 auto other = type.construct();
1569 const auto value = from.conversion_helper(nullptr, storage.data());
1570 other.fetch_node().conversion_helper(other.storage.data(), &value);
1571 return other;
1572 }
1573
1574 if(const auto &from = fetch_node(); from.details) {
1575 if(const auto *elem = internal::find_member<&internal::meta_conv_node::type>(from.details->conv, type.info().hash()); elem != nullptr) {
1576 return elem->conv(*ctx, storage.data());
1577 }
1578
1579 for(auto &&curr: from.details->base) {
1580 if(auto other = curr.resolve(internal::meta_context::from(*ctx)).from_void(*ctx, nullptr, curr.cast(storage.data())); curr.type == type.info().hash()) {
1581 return other;
1582 } else if(auto from_base = std::as_const(other).allow_cast(type); from_base) {
1583 return from_base;
1584 }
1585 }
1586 }
1587 }
1588
1589 return meta_any{meta_ctx_arg, *ctx};
1590}
1591
1592[[nodiscard]] inline bool meta_any::allow_cast(const meta_type &type) {
1593 if(storage.has_value(type.info())) {
1594 return true;
1595 } else if(auto other = std::as_const(*this).allow_cast(type); other) {
1596 if(other.storage.owner()) {
1597 std::swap(*this, other);
1598 }
1599
1600 return true;
1601 }
1602
1603 return false;
1604}
1605
1606inline bool meta_any::assign(const meta_any &other) {
1607 if(!storage.assign(other.storage)) {
1608 auto value = other.allow_cast(type());
1609 return storage.assign(value.storage);
1610 }
1611
1612 return true;
1613}
1614
1615inline bool meta_any::assign(meta_any &&other) {
1616 return storage.assign(std::move(other.storage)) || storage.assign(std::as_const(other).allow_cast(type()).storage);
1617}
1618
1619[[nodiscard]] inline meta_type meta_data::type() const noexcept {
1620 return meta_type{*ctx, node_or_assert().type(internal::meta_context::from(*ctx))};
1621}
1622
1623[[nodiscard]] inline meta_type meta_data::arg(const size_type index) const noexcept {
1624 return index < arity() ? node_or_assert().arg(*ctx, index) : meta_type{};
1625}
1626
1627[[nodiscard]] inline meta_type meta_func::ret() const noexcept {
1628 return meta_type{*ctx, node_or_assert().ret(internal::meta_context::from(*ctx))};
1629}
1630
1631[[nodiscard]] inline meta_type meta_func::arg(const size_type index) const noexcept {
1632 return index < arity() ? node_or_assert().arg(*ctx, index) : meta_type{};
1633}
1634
1636class meta_sequence_container::meta_iterator final {
1637 using vtable_type = void(const void *, const std::ptrdiff_t, meta_any *);
1638
1639 template<typename It>
1640 static void basic_vtable(const void *value, const std::ptrdiff_t offset, meta_any *other) {
1641 const auto &it = *static_cast<const It *>(value);
1642 other ? other->emplace<decltype(*it)>(*it) : std::advance(const_cast<It &>(it), offset);
1643 }
1644
1645public:
1646 using value_type = meta_any;
1647 using pointer = input_iterator_pointer<value_type>;
1648 using reference = value_type;
1649 using difference_type = std::ptrdiff_t;
1650 using iterator_category = std::input_iterator_tag;
1651 using iterator_concept = std::bidirectional_iterator_tag;
1652
1653 meta_iterator() = default;
1654
1655 template<typename It>
1656 meta_iterator(const meta_ctx &area, It iter) noexcept
1657 : ctx{&area},
1658 vtable{&basic_vtable<It>},
1659 handle{iter} {}
1660
1661 meta_iterator &operator++() noexcept {
1662 return vtable(handle.data(), 1, nullptr), *this;
1663 }
1664
1665 meta_iterator operator++(int value) noexcept {
1666 meta_iterator orig = *this;
1667 vtable(handle.data(), ++value, nullptr);
1668 return orig;
1669 }
1670
1671 meta_iterator &operator--() noexcept {
1672 return vtable(handle.data(), -1, nullptr), *this;
1673 }
1674
1675 meta_iterator operator--(int value) noexcept {
1676 meta_iterator orig = *this;
1677 vtable(handle.data(), --value, nullptr);
1678 return orig;
1679 }
1680
1681 [[nodiscard]] reference operator*() const {
1682 reference other{meta_ctx_arg, *ctx};
1683 vtable(handle.data(), 0, &other);
1684 return other;
1685 }
1686
1687 [[nodiscard]] pointer operator->() const {
1688 return operator*();
1689 }
1690
1691 [[nodiscard]] explicit operator bool() const noexcept {
1692 return (vtable != nullptr);
1693 }
1694
1695 [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
1696 return handle == other.handle;
1697 }
1698
1699 [[nodiscard]] const any &base() const noexcept {
1700 return handle;
1701 }
1702
1703private:
1704 const meta_ctx *ctx{};
1705 vtable_type *vtable{};
1706 any handle{};
1707};
1708
1709[[nodiscard]] inline bool operator!=(const meta_sequence_container::iterator &lhs, const meta_sequence_container::iterator &rhs) noexcept {
1710 return !(lhs == rhs);
1711}
1712
1713class meta_associative_container::meta_iterator final {
1714 using vtable_type = void(const void *, std::pair<meta_any, meta_any> *);
1715
1716 template<bool KeyOnly, typename It>
1717 static void basic_vtable(const void *value, std::pair<meta_any, meta_any> *other) {
1718 if(const auto &it = *static_cast<const It *>(value); other) {
1719 if constexpr(KeyOnly) {
1720 other->first.emplace<decltype(*it)>(*it);
1721 } else {
1722 other->first.emplace<decltype((it->first))>(it->first);
1723 other->second.emplace<decltype((it->second))>(it->second);
1724 }
1725 } else {
1726 ++const_cast<It &>(it);
1727 }
1728 }
1729
1730public:
1731 using value_type = std::pair<meta_any, meta_any>;
1732 using pointer = input_iterator_pointer<value_type>;
1733 using reference = value_type;
1734 using difference_type = std::ptrdiff_t;
1735 using iterator_category = std::input_iterator_tag;
1736 using iterator_concept = std::forward_iterator_tag;
1737
1738 meta_iterator() = default;
1739
1740 template<bool KeyOnly, typename It>
1741 meta_iterator(const meta_ctx &area, std::bool_constant<KeyOnly>, It iter) noexcept
1742 : ctx{&area},
1743 vtable{&basic_vtable<KeyOnly, It>},
1744 handle{iter} {}
1745
1746 meta_iterator &operator++() noexcept {
1747 return vtable(handle.data(), nullptr), *this;
1748 }
1749
1750 meta_iterator operator++(int) noexcept {
1751 meta_iterator orig = *this;
1752 vtable(handle.data(), nullptr);
1753 return orig;
1754 }
1755
1756 [[nodiscard]] reference operator*() const {
1757 reference other{{meta_ctx_arg, *ctx}, {meta_ctx_arg, *ctx}};
1758 vtable(handle.data(), &other);
1759 return other;
1760 }
1761
1762 [[nodiscard]] pointer operator->() const {
1763 return operator*();
1764 }
1765
1766 [[nodiscard]] explicit operator bool() const noexcept {
1767 return (vtable != nullptr);
1768 }
1769
1770 [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
1771 return handle == other.handle;
1772 }
1773
1774private:
1775 const meta_ctx *ctx{};
1776 vtable_type *vtable{};
1777 any handle{};
1778};
1779
1780[[nodiscard]] inline bool operator!=(const meta_associative_container::iterator &lhs, const meta_associative_container::iterator &rhs) noexcept {
1781 return !(lhs == rhs);
1782}
1784
1789[[nodiscard]] inline meta_type meta_sequence_container::value_type() const noexcept {
1790 return (value_type_node != nullptr) ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1791}
1792
1798 return size_fn(data);
1799}
1800
1807 return !const_only && resize_fn(const_cast<void *>(data), sz);
1808}
1809
1815 return !const_only && clear_fn(const_cast<void *>(data));
1816}
1817
1824 return !const_only && reserve_fn(const_cast<void *>(data), sz);
1825}
1826
1832 return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, false);
1833}
1834
1840 return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, true);
1841}
1842
1850 // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
1851 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))}))) {
1852 const bool is_value_type = (value.type().info() == *vtype.info);
1853 return insert_fn(*ctx, const_cast<void *>(data), is_value_type ? value.base().data() : nullptr, is_value_type ? nullptr : value.base().data(), it);
1854 }
1855
1856 return iterator{};
1857}
1858
1865 return const_only ? iterator{} : erase_fn(*ctx, const_cast<void *>(data), it);
1866}
1867
1874 auto it = begin();
1875 it.operator++(static_cast<int>(pos) - 1);
1876 return *it;
1877}
1878
1883[[nodiscard]] inline meta_sequence_container::operator bool() const noexcept {
1884 return (data != nullptr);
1885}
1886
1891[[nodiscard]] inline meta_type meta_associative_container::key_type() const noexcept {
1892 return (key_type_node != nullptr) ? meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1893}
1894
1899[[nodiscard]] inline meta_type meta_associative_container::mapped_type() const noexcept {
1900 return (mapped_type_node != nullptr) ? meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1901}
1902
1904[[nodiscard]] inline meta_type meta_associative_container::value_type() const noexcept {
1905 return (value_type_node != nullptr) ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1906}
1907
1910 return size_fn(data);
1911}
1912
1915 return !const_only && clear_fn(const_cast<void *>(data));
1916}
1917
1920 return !const_only && reserve_fn(const_cast<void *>(data), sz);
1921}
1922
1925 return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, false);
1926}
1927
1930 return begin_end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, true);
1931}
1932
1940 return !const_only && key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})
1941 && ((mapped_type_node == nullptr) || value.allow_cast(meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))}))
1942 && insert_fn(const_cast<void *>(data), key.base().data(), value.base().data());
1943}
1944
1951 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;
1952}
1953
1960 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{};
1961}
1962
1967[[nodiscard]] inline meta_associative_container::operator bool() const noexcept {
1968 return (data != nullptr);
1969}
1970
1971} // namespace entt
1972
1973#endif
const void * data() const noexcept
Returns an opaque pointer to the contained instance.
Definition any.hpp:366
any_policy policy() const noexcept
Returns the current mode of an any object.
Definition any.hpp:527
Service locator, nothing more.
Definition locator.hpp:27
static Service & value_or(Args &&...args)
Returns a service if available or sets it from a fallback type.
Definition locator.hpp:88
Opaque wrapper for values of any type.
Definition meta.hpp:159
bool assign(const meta_any &other)
Assigns a value to the contained object without replacing it.
Definition meta.hpp:1606
meta_any & operator=(const meta_any &other)
Copy assignment operator.
Definition meta.hpp:340
meta_associative_container as_associative_container() noexcept
Returns an associative container proxy.
Definition meta.hpp:567
meta_type type() const noexcept
Returns the object type info if any, type_id<void>() otherwise.
Definition meta.hpp:1535
meta_any(const meta_ctx &area, const meta_any &other)
Context aware copy constructor.
Definition meta.hpp:299
meta_any()=default
meta_any invoke(id_type id, Args &&...args) const
Invokes the underlying function, if possible.
Definition meta.hpp:1541
std::remove_const_t< Type > cast()
Tries to cast an instance to a given type.
Definition meta.hpp:444
~meta_any()=default
Default destructor.
meta_any(meta_any &&other) noexcept
Move constructor.
Definition meta.hpp:326
meta_any(std::in_place_type_t< Type >, Args &&...args)
Constructs a wrapper by directly initializing the new object.
Definition meta.hpp:237
std::remove_const_t< Type > cast() const
Tries to cast an instance to a given type.
Definition meta.hpp:436
meta_any as_ref() noexcept
Aliasing constructor.
Definition meta.hpp:607
const Type * try_cast() const
Tries to cast an instance to a given type.
Definition meta.hpp:419
void emplace(Args &&...args)
Replaces the contained object by creating a new instance directly.
Definition meta.hpp:527
meta_any(std::in_place_t, Type *value)
Constructs a wrapper taking ownership of the passed object.
Definition meta.hpp:259
meta_any(const meta_ctx &area, meta_any &&other)
Context aware move constructor.
Definition meta.hpp:310
meta_sequence_container as_sequence_container() noexcept
Returns a sequence container proxy.
Definition meta.hpp:550
Type * try_cast()
Tries to cast an instance to a given type.
Definition meta.hpp:426
meta_associative_container as_associative_container() const noexcept
Returns an associative container proxy.
Definition meta.hpp:574
meta_any(const meta_any &other)=default
Copy constructor.
meta_any operator*() const noexcept
Indirection operator for dereferencing opaque objects.
Definition meta.hpp:585
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:1563
meta_any(const meta_ctx &area, Type &&value)
Constructs a wrapper from a given value.
Definition meta.hpp:291
meta_any(const meta_ctx &area, std::in_place_type_t< Type >, Args &&...args)
Constructs a wrapper by directly initializing the new object.
Definition meta.hpp:248
const any & base() const noexcept
Returns the underlying storage.
Definition meta.hpp:620
meta_any as_ref() const noexcept
Aliasing constructor.
Definition meta.hpp:612
meta_any allow_cast() const
Converts an object in such a way that a given cast becomes viable.
Definition meta.hpp:471
meta_any(meta_ctx_arg_t, const meta_ctx &area)
Context aware constructor.
Definition meta.hpp:227
meta_any(Type &&value)
Constructs a wrapper from a given value.
Definition meta.hpp:281
void reset()
Destroys contained object.
Definition meta.hpp:540
meta_any & operator=(Type &&value)
Value assignment operator.
Definition meta.hpp:371
meta_any(const meta_ctx &area, std::in_place_t, Type *value)
Constructs a wrapper taking ownership of the passed object.
Definition meta.hpp:269
meta_sequence_container as_sequence_container() const noexcept
Returns a sequence container proxy.
Definition meta.hpp:557
bool operator==(const meta_any &other) const noexcept
Checks if two wrappers differ in their content.
Definition meta.hpp:597
bool operator!=(const meta_any &other) const noexcept
Checks if two wrappers differ in their content.
Definition meta.hpp:602
bool set(id_type id, Type &&value)
Sets the value of a given variable.
Definition meta.hpp:1551
bool allow_cast()
Converts an object in such a way that a given cast becomes viable.
Definition meta.hpp:507
meta_any get(id_type id) const
Gets the value of a given variable.
Definition meta.hpp:1555
meta_any & operator=(meta_any &&other) noexcept
Move assignment operator.
Definition meta.hpp:356
const meta_ctx & context() const noexcept
Returns the underlying meta context.
Definition meta.hpp:628
Proxy object for associative containers.
Definition meta.hpp:92
meta_associative_container()=default
Default constructor.
size_type erase(meta_any)
Removes the specified element from a container.
Definition meta.hpp:1950
iterator find(meta_any)
Returns an iterator to the element with a given key, if any.
Definition meta.hpp:1959
bool insert(meta_any, meta_any)
Inserts a key-only or key/value element into a container.
Definition meta.hpp:1939
iterator end()
Returns an iterator that is past the last element of a container.
Definition meta.hpp:1929
bool reserve(size_type)
Reserves storage for at least the given number of elements.
Definition meta.hpp:1919
meta_associative_container(const meta_ctx &area, Type &instance) noexcept
Context aware constructor.
Definition meta.hpp:111
iterator begin()
Returns an iterator to the first element of a container.
Definition meta.hpp:1924
size_type size() const noexcept
Returns the size of a container.
Definition meta.hpp:1909
meta_type mapped_type() const noexcept
Returns the meta mapped type of a container.
Definition meta.hpp:1899
std::size_t size_type
Unsigned integer type.
Definition meta.hpp:97
meta_iterator iterator
Meta iterator type.
Definition meta.hpp:99
meta_type value_type() const noexcept
Returns the meta value type of a container.
Definition meta.hpp:1904
meta_type key_type() const noexcept
Returns the meta key type of a container.
Definition meta.hpp:1891
bool clear()
Clears the content of a container.
Definition meta.hpp:1914
Disambiguation tag for constructors and the like.
Definition context.hpp:28
Opaque meta context type.
Definition context.hpp:34
Opaque wrapper for data members.
Definition meta.hpp:785
bool is_const() const noexcept
Indicates whether a data member is constant or not.
Definition meta.hpp:827
meta_type arg(size_type index) const noexcept
Returns the type accepted by the i-th setter.
Definition meta.hpp:1623
const char * name() const noexcept
Returns the name assigned to a data member, if any.
Definition meta.hpp:811
typename internal::meta_data_node::size_type size_type
Unsigned integer type.
Definition meta.hpp:793
size_type arity() const noexcept
Returns the number of setters available.
Definition meta.hpp:819
bool operator==(const meta_data &other) const noexcept
Checks if two objects refer to the same type.
Definition meta.hpp:905
bool set(Instance &&instance, Type &&value) const
Sets the value of a given variable.
Definition meta.hpp:852
meta_custom custom() const noexcept
Returns user defined data for a given meta object.
Definition meta.hpp:888
meta_type type() const noexcept
Returns the object type info if any, type_id<void>() otherwise.
Definition meta.hpp:1619
meta_data() noexcept=default
Default constructor.
bool is_static() const noexcept
Indicates whether a data member is static or not.
Definition meta.hpp:835
Type traits() const noexcept
Returns all meta traits for a given meta object.
Definition meta.hpp:880
meta_any get(Instance &&instance) const
Gets the value of a given variable.
Definition meta.hpp:863
Opaque wrapper for member functions.
Definition meta.hpp:925
bool is_static() const noexcept
Indicates whether a member function is static or not.
Definition meta.hpp:975
typename internal::meta_func_node::size_type size_type
Unsigned integer type.
Definition meta.hpp:933
meta_func() noexcept=default
Default constructor.
meta_type ret() const noexcept
Returns the return type of a member function.
Definition meta.hpp:1627
bool operator==(const meta_func &other) const noexcept
Checks if two objects refer to the same type.
Definition meta.hpp:1044
Type traits() const noexcept
Returns all meta traits for a given meta object.
Definition meta.hpp:1021
bool is_const() const noexcept
Indicates whether a member function is constant or not.
Definition meta.hpp:967
meta_any invoke(Instance &&instance, meta_any *const args, const size_type sz) const
Invokes the underlying function, if possible.
Definition meta.hpp:1001
const char * name() const noexcept
Returns the name assigned to a member function, if any.
Definition meta.hpp:951
meta_custom custom() const noexcept
Returns user defined data for a given meta object.
Definition meta.hpp:1026
meta_func next() const
Returns the next overload of a given function, if any.
Definition meta.hpp:1034
meta_type arg(size_type index) const noexcept
Returns the type of the i-th argument of a member function.
Definition meta.hpp:1631
size_type arity() const noexcept
Returns the number of arguments accepted by a member function.
Definition meta.hpp:959
meta_any invoke(Instance &&instance, Args &&...args) const
Invokes the underlying function, if possible.
Definition meta.hpp:1015
Opaque pointers to instances of any type.
Definition meta.hpp:663
meta_handle & operator=(const meta_handle &)=delete
Default copy assignment operator, deleted on purpose.
meta_handle(const meta_ctx &ctx, Type &value)
Creates a handle that points to an unmanaged object.
Definition meta.hpp:683
~meta_handle()=default
Default destructor.
meta_handle()=default
meta_handle(meta_handle &&)=default
Default move constructor.
meta_handle(const meta_ctx &area, meta_handle &&other)
Context aware move constructor.
Definition meta.hpp:700
const meta_any * operator->() const
Access operator for accessing the contained opaque object.
Definition meta.hpp:741
meta_handle(const meta_handle &)=delete
Default copy constructor, deleted on purpose.
meta_handle(Type &value)
Creates a handle that points to an unmanaged object.
Definition meta.hpp:692
meta_handle & operator=(meta_handle &&)=default
Default move assignment operator.
meta_any * operator->()
Access operator for accessing the contained opaque object.
Definition meta.hpp:736
Proxy object for sequence containers.
Definition meta.hpp:31
bool reserve(size_type)
Reserves storage for at least the given number of elements.
Definition meta.hpp:1823
iterator insert(const iterator &, meta_any)
Inserts an element at a specified location of a container.
Definition meta.hpp:1849
meta_type value_type() const noexcept
Returns the meta value type of a container.
Definition meta.hpp:1789
meta_any operator[](size_type)
Returns a reference to the element at a given location of a container.
Definition meta.hpp:1873
meta_sequence_container()=default
Default constructor.
iterator end()
Returns an iterator that is past the last element of a container.
Definition meta.hpp:1839
iterator erase(const iterator &)
Removes a given element from a container.
Definition meta.hpp:1864
meta_sequence_container(const meta_ctx &area, Type &instance) noexcept
Context aware constructor.
Definition meta.hpp:50
meta_iterator iterator
Meta iterator type.
Definition meta.hpp:38
std::size_t size_type
Unsigned integer type.
Definition meta.hpp:36
bool resize(size_type)
Resizes a container to contain a given number of elements.
Definition meta.hpp:1806
size_type size() const noexcept
Returns the size of a container.
Definition meta.hpp:1797
iterator begin()
Returns an iterator to the first element of a container.
Definition meta.hpp:1831
bool clear()
Clears the content of a container.
Definition meta.hpp:1814
Opaque wrapper for types.
Definition meta.hpp:1059
bool is_pointer() const noexcept
Checks whether a type refers to a pointer or not.
Definition meta.hpp:1226
bool is_arithmetic() const noexcept
Checks whether a type refers to an arithmetic type or not.
Definition meta.hpp:1178
meta_range< meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator > func() const noexcept
Returns a range to visit registered top-level functions.
Definition meta.hpp:1362
meta_custom custom() const noexcept
Returns user defined data for a given meta object.
Definition meta.hpp:1511
meta_any from_void(void *elem, bool transfer_ownership=false) const
Wraps an opaque element of the underlying type.
Definition meta.hpp:1416
id_type id() const noexcept
Returns the identifier assigned to a type.
Definition meta.hpp:1153
meta_any invoke(const id_type id, Instance &&instance, Args &&...args) const
Invokes a function given an identifier, if possible.
Definition meta.hpp:1471
bool set(const id_type id, Instance &&instance, Type &&value) const
Sets the value of a given variable.
Definition meta.hpp:1486
meta_type remove_pointer() const noexcept
Provides the type for which the pointer is defined.
Definition meta.hpp:1235
meta_any construct(Args &&...args) const
Creates an instance of the underlying type, if possible.
Definition meta.hpp:1405
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:1292
bool is_array() const noexcept
Checks whether a type refers to an array type or not.
Definition meta.hpp:1202
meta_data data(const id_type id, const bool recursive=true) const
Lookup utility for meta data (bases are also visited).
Definition meta.hpp:1353
bool is_class() const noexcept
Checks whether a type refers to a class or not.
Definition meta.hpp:1218
typename internal::meta_type_node::size_type size_type
Unsigned integer type.
Definition meta.hpp:1119
meta_any from_void(const void *elem) const
Wraps an opaque element of the underlying type.
Definition meta.hpp:1425
meta_range< meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator > data() const noexcept
Returns a range to visit registered top-level meta data.
Definition meta.hpp:1342
const char * name() const noexcept
Returns the name assigned to a type, if any.
Definition meta.hpp:1161
meta_any invoke(const id_type id, Instance &&instance, meta_any *const args, const size_type sz) const
Invokes a function given an identifier, if possible.
Definition meta.hpp:1440
bool can_convert(const meta_type &other) const noexcept
Checks whether a type supports conversion to another type.
Definition meta.hpp:1311
bool is_signed() const noexcept
Checks whether a type refers to a signed type or not.
Definition meta.hpp:1194
bool is_enum() const noexcept
Checks whether a type refers to an enum or not.
Definition meta.hpp:1210
bool can_cast(const meta_type &other) const noexcept
Checks if a type supports direct casting to another type.
Definition meta.hpp:1301
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:1521
meta_range< meta_type, typename 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:1333
meta_any get(const id_type id, Instance &&instance) const
Gets the value of a given variable.
Definition meta.hpp:1499
bool is_pointer_like() const noexcept
Checks whether a type is a pointer-like type or not.
Definition meta.hpp:1243
Type traits() const noexcept
Returns all meta traits for a given meta object.
Definition meta.hpp:1506
meta_func func(const id_type id, const bool recursive=true) const
Lookup utility for meta functions (bases are also visited).
Definition meta.hpp:1373
meta_any construct(meta_any *const args, const size_type sz) const
Creates an instance of the underlying type, if possible.
Definition meta.hpp:1384
bool is_integral() const noexcept
Checks whether a type refers to an integral type or not.
Definition meta.hpp:1186
meta_type template_type() const noexcept
Returns a tag for the class template of the underlying type.
Definition meta.hpp:1283
meta_type(const meta_ctx &area, const internal::meta_base_node &curr) noexcept
Context aware constructor for meta objects.
Definition meta.hpp:1138
const type_info & info() const noexcept
Returns the type info object of the underlying type.
Definition meta.hpp:1145
bool is_template_specialization() const noexcept
Checks whether a type refers to a template specialization or not.
Definition meta.hpp:1267
bool is_associative_container() const noexcept
Checks whether a type refers to an associative container or not.
Definition meta.hpp:1259
size_type template_arity() const noexcept
Returns the number of template arguments.
Definition meta.hpp:1275
size_type size_of() const noexcept
Returns the size of the underlying type if known.
Definition meta.hpp:1169
bool is_sequence_container() const noexcept
Checks whether a type refers to a sequence container or not.
Definition meta.hpp:1251
EnTT default namespace.
Definition dense_map.hpp:22
basic_handle< registry > handle
Alias declaration for the most common use case.
Definition fwd.hpp:101
std::remove_const_t< Type > any_cast(const basic_any< Len, Align > &data) noexcept
Performs type-safe access to the contained object.
Definition any.hpp:547
std::uint32_t id_type
Alias declaration for type identifiers.
Definition fwd.hpp:29
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:147
constexpr bool is_complete_v
Helper variable template.
constexpr get_t< Type... > get
Variable template for lists of observed elements.
Definition fwd.hpp:167
constexpr meta_ctx_arg_t meta_ctx_arg
Constant of type meta_context_arg_t used to disambiguate calls.
Definition context.hpp:31
constexpr auto is_meta_pointer_like_v
Helper variable template.
@ in_place
In-place deletion policy.
Definition fwd.hpp:21
meta_any forward_as_meta(const meta_ctx &ctx, Type &&value)
Forwards its argument and avoids copies for lvalue references.
Definition meta.hpp:647
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
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
@ ref
Aliasing mode, non-const reference.
Definition fwd.hpp:19
@ cref
Const aliasing mode, const reference.
Definition fwd.hpp:21
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.
Definition fwd.hpp:78
static decltype(auto) dereference(const Type &value)
Uses the default ADL based lookup method to resolve the call.
Opaque wrapper for user defined data of any type.
Definition meta.hpp:750
meta_custom() noexcept=default
Default constructor.
Traits class template to be specialized to enable support for meta sequence containers.
Implementation specific information about a type.