EnTT 3.13.0
Loading...
Searching...
No Matches
meta.hpp
1#ifndef ENTT_META_META_HPP
2#define ENTT_META_META_HPP
3
4#include <cstddef>
5#include <iterator>
6#include <memory>
7#include <type_traits>
8#include <utility>
9#include "../config/config.h"
10#include "../core/any.hpp"
11#include "../core/fwd.hpp"
12#include "../core/iterator.hpp"
13#include "../core/type_info.hpp"
14#include "../core/type_traits.hpp"
15#include "../core/utility.hpp"
16#include "../locator/locator.hpp"
17#include "adl_pointer.hpp"
18#include "context.hpp"
19#include "fwd.hpp"
20#include "node.hpp"
21#include "range.hpp"
22#include "type_traits.hpp"
23
24namespace entt {
25
26class meta_any;
27class meta_type;
28
31 class meta_iterator;
32
33public:
35 using size_type = std::size_t;
37 using iterator = meta_iterator;
38
42
47 meta_sequence_container(const meta_ctx &area) noexcept
48 : ctx{&area} {}
49
55 template<typename Type>
56 void rebind(Type &instance) noexcept {
57 value_type_node = &internal::resolve<typename Type::value_type>;
58 const_reference_node = &internal::resolve<std::remove_const_t<std::remove_reference_t<typename Type::const_reference>>>;
67 const_only = std::is_const_v<Type>;
68 data = &instance;
69 }
70
71 [[nodiscard]] inline meta_type value_type() const noexcept;
72 [[nodiscard]] inline size_type size() const noexcept;
73 inline bool resize(const size_type);
74 inline bool clear();
75 inline bool reserve(const size_type);
76 [[nodiscard]] inline iterator begin();
77 [[nodiscard]] inline iterator end();
79 inline iterator erase(iterator);
80 [[nodiscard]] inline meta_any operator[](const size_type);
81 [[nodiscard]] inline explicit operator bool() const noexcept;
82
83private:
84 const meta_ctx *ctx{};
85 internal::meta_type_node (*value_type_node)(const internal::meta_context &){};
86 internal::meta_type_node (*const_reference_node)(const internal::meta_context &){};
87 size_type (*size_fn)(const void *){};
88 bool (*clear_fn)(void *){};
89 bool (*reserve_fn)(void *, const size_type){};
90 bool (*resize_fn)(void *, const size_type){};
91 iterator (*begin_fn)(const meta_ctx &, void *, const void *){};
92 iterator (*end_fn)(const meta_ctx &, void *, const void *){};
93 iterator (*insert_fn)(const meta_ctx &, void *, const void *, const void *, const iterator &){};
94 iterator (*erase_fn)(const meta_ctx &, void *, const iterator &){};
95 const void *data{};
96 bool const_only{};
97};
98
101 class meta_iterator;
102
103public:
105 using size_type = std::size_t;
107 using iterator = meta_iterator;
108
112
118 : ctx{&area} {}
119
125 template<typename Type>
126 void rebind(Type &instance) noexcept {
127 key_type_node = &internal::resolve<typename Type::key_type>;
128 value_type_node = &internal::resolve<typename Type::value_type>;
129
131 mapped_type_node = &internal::resolve<typename Type::mapped_type>;
132 }
133
142 const_only = std::is_const_v<Type>;
143 data = &instance;
144 }
145
146 [[nodiscard]] inline bool key_only() const noexcept;
147 [[nodiscard]] inline meta_type key_type() const noexcept;
148 [[nodiscard]] inline meta_type mapped_type() const noexcept;
149 [[nodiscard]] inline meta_type value_type() const noexcept;
150 [[nodiscard]] inline size_type size() const noexcept;
151 inline bool clear();
152 inline bool reserve(const size_type);
153 [[nodiscard]] inline iterator begin();
154 [[nodiscard]] inline iterator end();
155 inline bool insert(meta_any, meta_any);
156 inline size_type erase(meta_any);
157 [[nodiscard]] inline iterator find(meta_any);
158 [[nodiscard]] inline explicit operator bool() const noexcept;
159
160private:
161 const meta_ctx *ctx{};
162 internal::meta_type_node (*key_type_node)(const internal::meta_context &){};
163 internal::meta_type_node (*mapped_type_node)(const internal::meta_context &){};
164 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_fn)(const meta_ctx &, void *, const void *){};
169 iterator (*end_fn)(const meta_ctx &, void *, const void *){};
170 bool (*insert_fn)(void *, const void *, const void *){};
171 size_type (*erase_fn)(void *, const void *){};
172 iterator (*find_fn)(const meta_ctx &, void *, const void *, const void *){};
173 const void *data{};
174 bool const_only{};
175};
176
179
181class meta_any {
182 using vtable_type = void(const internal::meta_traits op, const bool, const void *, void *);
183
184 template<typename Type>
185 static std::enable_if_t<std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>> basic_vtable([[maybe_unused]] const internal::meta_traits req, [[maybe_unused]] const bool const_only, [[maybe_unused]] const void *value, [[maybe_unused]] void *other) {
186 if constexpr(is_meta_pointer_like_v<Type>) {
187 if(req == internal::meta_traits::is_meta_pointer_like) {
188 if constexpr(std::is_function_v<typename std::pointer_traits<Type>::element_type>) {
189 static_cast<meta_any *>(other)->emplace<Type>(*static_cast<const Type *>(value));
190 } else if constexpr(!std::is_void_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) {
191 using in_place_type = decltype(adl_meta_pointer_like<Type>::dereference(*static_cast<const Type *>(value)));
192
193 if constexpr(std::is_constructible_v<bool, Type>) {
194 if(const auto &pointer_like = *static_cast<const Type *>(value); pointer_like) {
195 static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(pointer_like));
196 }
197 } else {
198 static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(*static_cast<const Type *>(value)));
199 }
200 }
201 }
202 }
203
204 if constexpr(is_complete_v<meta_sequence_container_traits<Type>>) {
205 if(req == internal::meta_traits::is_meta_sequence_container) {
206 const_only ? static_cast<meta_sequence_container *>(other)->rebind(*static_cast<const Type *>(value)) : static_cast<meta_sequence_container *>(other)->rebind(*static_cast<Type *>(const_cast<void *>(value)));
207 }
208 }
209
210 if constexpr(is_complete_v<meta_associative_container_traits<Type>>) {
211 if(req == internal::meta_traits::is_meta_associative_container) {
212 const_only ? static_cast<meta_associative_container *>(other)->rebind(*static_cast<const Type *>(value)) : static_cast<meta_associative_container *>(other)->rebind(*static_cast<Type *>(const_cast<void *>(value)));
213 }
214 }
215 }
216
217 void release() {
218 if(node.dtor.dtor && (storage.policy() == any_policy::owner)) {
219 node.dtor.dtor(storage.data());
220 }
221 }
222
223 meta_any(const meta_ctx &area, const meta_any &other, any ref) noexcept
224 : storage{std::move(ref)},
225 ctx{&area},
226 node{storage ? other.node : internal::meta_type_node{}},
227 vtable{storage ? other.vtable : &basic_vtable<void>} {}
228
229public:
231 meta_any() noexcept
233
238 meta_any(meta_ctx_arg_t, const meta_ctx &area) noexcept
239 : storage{},
240 ctx{&area},
241 node{},
242 vtable{&basic_vtable<void>} {}
243
250 template<typename Type, typename... Args>
251 explicit meta_any(std::in_place_type_t<Type>, Args &&...args)
252 : meta_any{locator<meta_ctx>::value_or(), std::in_place_type<Type>, std::forward<Args>(args)...} {}
253
261 template<typename Type, typename... Args>
262 explicit meta_any(const meta_ctx &area, std::in_place_type_t<Type>, Args &&...args)
263 : storage{std::in_place_type<Type>, std::forward<Args>(args)...},
264 ctx{&area},
265 node{internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx))},
266 vtable{&basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>} {}
267
273 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
274 meta_any(Type &&value)
275 : meta_any{locator<meta_ctx>::value_or(), std::forward<Type>(value)} {}
276
283 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
284 meta_any(const meta_ctx &area, Type &&value)
285 : meta_any{area, std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
286
292 meta_any(const meta_ctx &area, const meta_any &other)
293 : meta_any{other} {
294 ctx = &area;
295 node = node.resolve ? node.resolve(internal::meta_context::from(*ctx)) : node;
296 }
297
303 meta_any(const meta_ctx &area, meta_any &&other)
304 : meta_any{std::move(other)} {
305 ctx = &area;
306 node = node.resolve ? node.resolve(internal::meta_context::from(*ctx)) : node;
307 }
308
313 meta_any(const meta_any &other) = default;
314
319 meta_any(meta_any &&other) noexcept
320 : storage{std::move(other.storage)},
321 ctx{other.ctx},
322 node{std::exchange(other.node, internal::meta_type_node{})},
323 vtable{std::exchange(other.vtable, &basic_vtable<void>)} {}
324
327 release();
328 }
329
335 meta_any &operator=(const meta_any &other) {
336 release();
337 storage = other.storage;
338 ctx = other.ctx;
339 node = other.node;
340 vtable = other.vtable;
341 return *this;
342 }
343
349 meta_any &operator=(meta_any &&other) noexcept {
350 release();
351 storage = std::move(other.storage);
352 ctx = other.ctx;
353 node = std::exchange(other.node, internal::meta_type_node{});
354 vtable = std::exchange(other.vtable, &basic_vtable<void>);
355 return *this;
356 }
357
364 template<typename Type>
365 std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>, meta_any &>
366 operator=(Type &&value) {
367 emplace<std::decay_t<Type>>(std::forward<Type>(value));
368 return *this;
369 }
370
372 [[nodiscard]] inline meta_type type() const noexcept;
373
375 [[nodiscard]] const void *data() const noexcept {
376 return storage.data();
377 }
378
380 [[nodiscard]] void *data() noexcept {
381 return storage.data();
382 }
383
391 template<typename... Args>
392 meta_any invoke(const id_type id, Args &&...args) const;
393
395 template<typename... Args>
396 meta_any invoke(const id_type id, Args &&...args);
397
405 template<typename Type>
406 bool set(const id_type id, Type &&value);
407
413 [[nodiscard]] meta_any get(const id_type id) const;
414
416 [[nodiscard]] meta_any get(const id_type id);
417
423 template<typename Type>
424 [[nodiscard]] const Type *try_cast() const {
425 const auto other = internal::resolve<std::remove_cv_t<Type>>(internal::meta_context::from(*ctx));
426 return static_cast<const Type *>(internal::try_cast(internal::meta_context::from(*ctx), node, other, data()));
427 }
428
430 template<typename Type>
431 [[nodiscard]] Type *try_cast() {
432 if constexpr(std::is_const_v<Type>) {
433 return std::as_const(*this).try_cast<std::remove_const_t<Type>>();
434 } else {
435 const auto other = internal::resolve<std::remove_cv_t<Type>>(internal::meta_context::from(*ctx));
436 return static_cast<Type *>(const_cast<void *>(internal::try_cast(internal::meta_context::from(*ctx), node, other, data())));
437 }
438 }
439
445 template<typename Type>
446 [[nodiscard]] Type cast() const {
447 auto *const instance = try_cast<std::remove_reference_t<Type>>();
448 ENTT_ASSERT(instance, "Invalid instance");
449 return static_cast<Type>(*instance);
450 }
451
453 template<typename Type>
454 [[nodiscard]] Type cast() {
455 // forces const on non-reference types to make them work also with wrappers for const references
456 auto *const instance = try_cast<std::remove_reference_t<const Type>>();
457 ENTT_ASSERT(instance, "Invalid instance");
458 return static_cast<Type>(*instance);
459 }
460
467 [[nodiscard]] meta_any allow_cast(const meta_type &type) const;
468
474 [[nodiscard]] bool allow_cast(const meta_type &type) {
475 if(auto other = std::as_const(*this).allow_cast(type); other) {
476 if((other.storage.policy() == any_policy::owner)) {
477 std::swap(*this, other);
478 }
479
480 return true;
481 }
482
483 return false;
484 }
485
492 template<typename Type>
493 [[nodiscard]] meta_any allow_cast() const {
494 if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
495 return meta_any{meta_ctx_arg, *ctx};
496 } else {
497 auto other = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
498 return allow_cast(meta_type{*ctx, other});
499 }
500 }
501
507 template<typename Type>
508 [[nodiscard]] bool allow_cast() {
509 auto other = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
510 return allow_cast(meta_type{*ctx, other}) && (!(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) || storage.data() != nullptr);
511 }
512
514 template<typename Type, typename... Args>
515 void emplace(Args &&...args) {
516 release();
517 storage.emplace<Type>(std::forward<Args>(args)...);
518 node = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
519 vtable = &basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
520 }
521
523 bool assign(const meta_any &other);
524
526 bool assign(meta_any &&other);
527
529 void reset() {
530 release();
531 storage.reset();
532 node = {};
533 vtable = &basic_vtable<void>;
534 }
535
541 meta_sequence_container proxy{*ctx};
542 vtable(internal::meta_traits::is_meta_sequence_container, policy() == meta_any_policy::cref, std::as_const(*this).data(), &proxy);
543 return proxy;
544 }
545
547 [[nodiscard]] meta_sequence_container as_sequence_container() const noexcept {
548 meta_sequence_container proxy{*ctx};
549 vtable(internal::meta_traits::is_meta_sequence_container, true, data(), &proxy);
550 return proxy;
551 }
552
558 meta_associative_container proxy{*ctx};
559 vtable(internal::meta_traits::is_meta_associative_container, policy() == meta_any_policy::cref, std::as_const(*this).data(), &proxy);
560 return proxy;
561 }
562
565 meta_associative_container proxy{*ctx};
566 vtable(internal::meta_traits::is_meta_associative_container, true, data(), &proxy);
567 return proxy;
568 }
569
575 [[nodiscard]] meta_any operator*() const noexcept {
576 meta_any ret{meta_ctx_arg, *ctx};
577 vtable(internal::meta_traits::is_meta_pointer_like, true, storage.data(), &ret);
578 return ret;
579 }
580
585 [[nodiscard]] explicit operator bool() const noexcept {
586 return !(node.info == nullptr);
587 }
588
590 [[nodiscard]] bool operator==(const meta_any &other) const noexcept {
591 return (ctx == other.ctx) && ((!node.info && !other.node.info) || (node.info && other.node.info && *node.info == *other.node.info && storage == other.storage));
592 }
593
595 [[nodiscard]] bool operator!=(const meta_any &other) const noexcept {
596 return !(*this == other);
597 }
598
600 [[nodiscard]] meta_any as_ref() noexcept {
601 return meta_any{*ctx, *this, storage.as_ref()};
602 }
603
605 [[nodiscard]] meta_any as_ref() const noexcept {
606 return meta_any{*ctx, *this, storage.as_ref()};
607 }
608
610 [[deprecated("use policy() and meta_any_policy instead")]] [[nodiscard]] bool owner() const noexcept {
611 return (storage.policy() == any_policy::owner);
612 }
613
618 [[nodiscard]] meta_any_policy policy() const noexcept {
619 return storage.policy();
620 }
621
622private:
623 any storage;
624 const meta_ctx *ctx;
625 internal::meta_type_node node;
626 vtable_type *vtable;
627};
628
636template<typename Type>
637[[nodiscard]] meta_any forward_as_meta(const meta_ctx &ctx, Type &&value) {
638 return meta_any{ctx, std::in_place_type<Type &&>, std::forward<Type>(value)};
639}
640
647template<typename Type>
648[[nodiscard]] meta_any forward_as_meta(Type &&value) {
649 return forward_as_meta(locator<meta_ctx>::value_or(), std::forward<Type>(value));
650}
651
660 meta_handle() noexcept
662
667 meta_handle(meta_ctx_arg_t, const meta_ctx &area) noexcept
668 : any{meta_ctx_arg, area} {}
669
674 meta_handle(meta_any &value) noexcept
675 : any{value.as_ref()} {}
676
681 meta_handle(const meta_any &value) noexcept
682 : any{value.as_ref()} {}
683
690 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
691 meta_handle(const meta_ctx &ctx, Type &value) noexcept
692 : any{ctx, std::in_place_type<Type &>, value} {}
693
699 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
700 meta_handle(Type &value) noexcept
702
708 meta_handle(const meta_ctx &area, const meta_handle &other)
709 : any{area, other.any} {}
710
716 meta_handle(const meta_ctx &area, meta_handle &&other)
717 : any{area, std::move(other.any)} {}
718
720 meta_handle(const meta_handle &) = delete;
721
724
730
736
741 [[nodiscard]] explicit operator bool() const noexcept {
742 return static_cast<bool>(any);
743 }
744
746 [[nodiscard]] bool operator==(const meta_handle &other) const noexcept {
747 return (any == other.any);
748 }
749
751 [[nodiscard]] bool operator!=(const meta_handle &other) const noexcept {
752 return !(*this == other);
753 }
754
759 [[nodiscard]] meta_any *operator->() {
760 return &any;
761 }
762
764 [[nodiscard]] const meta_any *operator->() const {
765 return &any;
766 }
767
768private:
770};
771
773struct meta_prop {
775 meta_prop() noexcept
776 : node{},
777 ctx{} {}
778
784 meta_prop(const meta_ctx &area, const internal::meta_prop_node &curr) noexcept
785 : node{&curr},
786 ctx{&area} {}
787
792 [[nodiscard]] meta_any value() const {
793 return node->value ? node->type(internal::meta_context::from(*ctx)).from_void(*ctx, nullptr, node->value.get()) : meta_any{meta_ctx_arg, *ctx};
794 }
795
800 [[nodiscard]] meta_any value() {
801 return node->value ? node->type(internal::meta_context::from(*ctx)).from_void(*ctx, node->value.get(), nullptr) : meta_any{meta_ctx_arg, *ctx};
802 }
803
808 [[nodiscard]] explicit operator bool() const noexcept {
809 return (node != nullptr);
810 }
811
817 [[nodiscard]] bool operator==(const meta_prop &other) const noexcept {
818 return (ctx == other.ctx && node == other.node);
819 }
820
821private:
822 const internal::meta_prop_node *node;
823 const meta_ctx *ctx;
824};
825
832[[nodiscard]] inline bool operator!=(const meta_prop &lhs, const meta_prop &rhs) noexcept {
833 return !(lhs == rhs);
834}
835
837struct meta_data {
839 using size_type = typename internal::meta_data_node::size_type;
840
842 meta_data() noexcept
843 : node{},
844 ctx{} {}
845
851 meta_data(const meta_ctx &area, const internal::meta_data_node &curr) noexcept
852 : node{&curr},
853 ctx{&area} {}
854
859 [[nodiscard]] size_type arity() const noexcept {
860 return node->arity;
861 }
862
867 [[nodiscard]] bool is_const() const noexcept {
868 return static_cast<bool>(node->traits & internal::meta_traits::is_const);
869 }
870
875 [[nodiscard]] bool is_static() const noexcept {
876 return static_cast<bool>(node->traits & internal::meta_traits::is_static);
877 }
878
880 [[nodiscard]] inline meta_type type() const noexcept;
881
889 template<typename Type>
890 bool set(meta_handle instance, Type &&value) const {
891 return node->set && node->set(meta_handle{*ctx, std::move(instance)}, meta_any{*ctx, std::forward<Type>(value)});
892 }
893
899 [[nodiscard]] meta_any get(meta_handle instance) const {
900 return node->get(*ctx, meta_handle{*ctx, std::move(instance)});
901 }
902
908 [[nodiscard]] inline meta_type arg(const size_type index) const noexcept;
909
914 [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_data_node::prop)::const_iterator> prop() const noexcept {
915 return {{*ctx, node->prop.cbegin()}, {*ctx, node->prop.cend()}};
916 }
917
923 [[nodiscard]] meta_prop prop(const id_type key) const {
924 const auto it = node->prop.find(key);
925 return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{};
926 }
927
932 [[nodiscard]] explicit operator bool() const noexcept {
933 return (node != nullptr);
934 }
935
937 [[nodiscard]] bool operator==(const meta_data &other) const noexcept {
938 return (ctx == other.ctx && node == other.node);
939 }
940
941private:
942 const internal::meta_data_node *node;
943 const meta_ctx *ctx;
944};
945
952[[nodiscard]] inline bool operator!=(const meta_data &lhs, const meta_data &rhs) noexcept {
953 return !(lhs == rhs);
954}
955
957struct meta_func {
959 using size_type = typename internal::meta_func_node::size_type;
960
962 meta_func() noexcept
963 : node{},
964 ctx{} {}
965
971 meta_func(const meta_ctx &area, const internal::meta_func_node &curr) noexcept
972 : node{&curr},
973 ctx{&area} {}
974
979 [[nodiscard]] size_type arity() const noexcept {
980 return node->arity;
981 }
982
987 [[nodiscard]] bool is_const() const noexcept {
988 return static_cast<bool>(node->traits & internal::meta_traits::is_const);
989 }
990
995 [[nodiscard]] bool is_static() const noexcept {
996 return static_cast<bool>(node->traits & internal::meta_traits::is_static);
997 }
998
1003 [[nodiscard]] inline meta_type ret() const noexcept;
1004
1010 [[nodiscard]] inline meta_type arg(const size_type index) const noexcept;
1011
1023 meta_any invoke(meta_handle instance, meta_any *const args, const size_type sz) const {
1024 return sz == arity() ? node->invoke(*ctx, meta_handle{*ctx, std::move(instance)}, args) : meta_any{meta_ctx_arg, *ctx};
1025 }
1026
1034 template<typename... Args>
1035 meta_any invoke(meta_handle instance, Args &&...args) const {
1036 meta_any arguments[sizeof...(Args) + !sizeof...(Args)]{{*ctx, std::forward<Args>(args)}...};
1037 return invoke(std::move(instance), arguments, sizeof...(Args));
1038 }
1039
1041 [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_func_node::prop)::const_iterator> prop() const noexcept {
1042 return {{*ctx, node->prop.cbegin()}, {*ctx, node->prop.cend()}};
1043 }
1044
1050 [[nodiscard]] meta_prop prop(const id_type key) const {
1051 const auto it = node->prop.find(key);
1052 return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{};
1053 }
1054
1059 [[nodiscard]] meta_func next() const {
1060 return node->next ? meta_func{*ctx, *node->next} : meta_func{};
1061 }
1062
1067 [[nodiscard]] explicit operator bool() const noexcept {
1068 return (node != nullptr);
1069 }
1070
1072 [[nodiscard]] bool operator==(const meta_func &other) const noexcept {
1073 return (ctx == other.ctx && node == other.node);
1074 }
1075
1076private:
1077 const internal::meta_func_node *node;
1078 const meta_ctx *ctx;
1079};
1080
1087[[nodiscard]] inline bool operator!=(const meta_func &lhs, const meta_func &rhs) noexcept {
1088 return !(lhs == rhs);
1089}
1090
1093 template<typename Func>
1094 [[nodiscard]] auto lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, [[maybe_unused]] bool constness, Func next) const {
1095 decltype(next()) candidate = nullptr;
1096 size_type same{};
1097 bool ambiguous{};
1098
1099 for(auto curr = next(); curr; curr = next()) {
1100 if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) {
1101 if(constness && !static_cast<bool>(curr->traits & internal::meta_traits::is_const)) {
1102 continue;
1103 }
1104 }
1105
1106 if(curr->arity == sz) {
1107 size_type match{};
1108 size_type pos{};
1109
1110 for(; pos < sz && args[pos]; ++pos) {
1111 const auto other = curr->arg(*ctx, pos);
1112 const auto type = args[pos].type();
1113
1114 if(const auto &info = other.info(); info == type.info()) {
1115 ++match;
1116 } else if(!((type.node.details && (type.node.details->base.contains(info.hash()) || type.node.details->conv.contains(info.hash()))) || (type.node.conversion_helper && other.node.conversion_helper))) {
1117 break;
1118 }
1119 }
1120
1121 if(pos == sz) {
1122 if(!candidate || match > same) {
1123 candidate = curr;
1124 same = match;
1125 ambiguous = false;
1126 } else if(match == same) {
1127 if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) {
1128 if(static_cast<bool>(curr->traits & internal::meta_traits::is_const) != static_cast<bool>(candidate->traits & internal::meta_traits::is_const)) {
1129 candidate = static_cast<bool>(candidate->traits & internal::meta_traits::is_const) ? curr : candidate;
1130 ambiguous = false;
1131 continue;
1132 }
1133 }
1134
1135 ambiguous = true;
1136 }
1137 }
1138 }
1139 }
1140
1141 return ambiguous ? nullptr : candidate;
1142 }
1143
1144public:
1146 using size_type = typename internal::meta_type_node::size_type;
1147
1149 meta_type() noexcept
1150 : node{},
1151 ctx{} {}
1152
1158 meta_type(const meta_ctx &area, const internal::meta_type_node &curr) noexcept
1159 : node{curr},
1160 ctx{&area} {}
1161
1167 meta_type(const meta_ctx &area, const internal::meta_base_node &curr) noexcept
1168 : meta_type{area, curr.type(internal::meta_context::from(area))} {}
1169
1174 [[nodiscard]] const type_info &info() const noexcept {
1175 return *node.info;
1176 }
1177
1182 [[nodiscard]] id_type id() const noexcept {
1183 return node.id;
1184 }
1185
1190 [[nodiscard]] size_type size_of() const noexcept {
1191 return node.size_of;
1192 }
1193
1199 [[nodiscard]] bool is_arithmetic() const noexcept {
1200 return static_cast<bool>(node.traits & internal::meta_traits::is_arithmetic);
1201 }
1202
1207 [[nodiscard]] bool is_integral() const noexcept {
1208 return static_cast<bool>(node.traits & internal::meta_traits::is_integral);
1209 }
1210
1215 [[nodiscard]] bool is_signed() const noexcept {
1216 return static_cast<bool>(node.traits & internal::meta_traits::is_signed);
1217 }
1218
1223 [[nodiscard]] bool is_array() const noexcept {
1224 return static_cast<bool>(node.traits & internal::meta_traits::is_array);
1225 }
1226
1231 [[nodiscard]] bool is_enum() const noexcept {
1232 return static_cast<bool>(node.traits & internal::meta_traits::is_enum);
1233 }
1234
1239 [[nodiscard]] bool is_class() const noexcept {
1240 return static_cast<bool>(node.traits & internal::meta_traits::is_class);
1241 }
1242
1247 [[nodiscard]] bool is_pointer() const noexcept {
1248 return node.info && (node.info->hash() != remove_pointer().info().hash());
1249 }
1250
1256 [[nodiscard]] meta_type remove_pointer() const noexcept {
1257 return {*ctx, node.remove_pointer(internal::meta_context::from(*ctx))}; // NOLINT
1258 }
1259
1264 [[nodiscard]] bool is_pointer_like() const noexcept {
1265 return static_cast<bool>(node.traits & internal::meta_traits::is_meta_pointer_like);
1266 }
1267
1272 [[nodiscard]] bool is_sequence_container() const noexcept {
1273 return static_cast<bool>(node.traits & internal::meta_traits::is_meta_sequence_container);
1274 }
1275
1280 [[nodiscard]] bool is_associative_container() const noexcept {
1281 return static_cast<bool>(node.traits & internal::meta_traits::is_meta_associative_container);
1282 }
1283
1290 [[nodiscard]] bool is_template_specialization() const noexcept {
1291 return (node.templ.arity != 0u);
1292 }
1293
1298 [[nodiscard]] size_type template_arity() const noexcept {
1299 return node.templ.arity;
1300 }
1301
1306 [[nodiscard]] inline meta_type template_type() const noexcept {
1307 return node.templ.type ? meta_type{*ctx, node.templ.type(internal::meta_context::from(*ctx))} : meta_type{};
1308 }
1309
1315 [[nodiscard]] inline meta_type template_arg(const size_type index) const noexcept {
1316 return index < template_arity() ? meta_type{*ctx, node.templ.arg(internal::meta_context::from(*ctx), index)} : meta_type{};
1317 }
1318
1324 [[nodiscard]] bool can_cast(const meta_type &other) const noexcept {
1325 // casting this is UB in all cases but we aren't going to use the resulting pointer, so...
1326 return (internal::try_cast(internal::meta_context::from(*ctx), node, other.node, this) != nullptr);
1327 }
1328
1334 [[nodiscard]] bool can_convert(const meta_type &other) const noexcept {
1335 return (internal::try_convert(internal::meta_context::from(*ctx), node, other.info(), other.is_arithmetic() || other.is_enum(), nullptr, [](const void *, auto &&...args) { return ((static_cast<void>(args), 1) + ... + 0u); }) != 0u);
1336 }
1337
1342 [[nodiscard]] meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator> base() const noexcept {
1343 using range_type = meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator>;
1344 return node.details ? range_type{{*ctx, node.details->base.cbegin()}, {*ctx, node.details->base.cend()}} : range_type{};
1345 }
1346
1351 [[nodiscard]] meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator> data() const noexcept {
1352 using range_type = meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator>;
1353 return node.details ? range_type{{*ctx, node.details->data.cbegin()}, {*ctx, node.details->data.cend()}} : range_type{};
1354 }
1355
1361 [[nodiscard]] meta_data data(const id_type id) const {
1362 const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), node, id);
1363 return elem ? meta_data{*ctx, *elem} : meta_data{};
1364 }
1365
1370 [[nodiscard]] meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator> func() const noexcept {
1371 using return_type = meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator>;
1372 return node.details ? return_type{{*ctx, node.details->func.cbegin()}, {*ctx, node.details->func.cend()}} : return_type{};
1373 }
1374
1383 [[nodiscard]] meta_func func(const id_type id) const {
1384 const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node, id);
1385 return elem ? meta_func{*ctx, *elem} : meta_func{};
1386 }
1387
1398 [[nodiscard]] meta_any construct(meta_any *const args, const size_type sz) const {
1399 if(node.details) {
1400 if(const auto *candidate = lookup(args, sz, false, [first = node.details->ctor.cbegin(), last = node.details->ctor.cend()]() mutable { return first == last ? nullptr : &(first++)->second; }); candidate) {
1401 return candidate->invoke(*ctx, args);
1402 }
1403 }
1404
1405 if(sz == 0u && node.default_constructor) {
1406 return node.default_constructor(*ctx);
1407 }
1408
1409 return meta_any{meta_ctx_arg, *ctx};
1410 }
1411
1418 template<typename... Args>
1419 [[nodiscard]] meta_any construct(Args &&...args) const {
1420 meta_any arguments[sizeof...(Args) + !sizeof...(Args)]{{*ctx, std::forward<Args>(args)}...};
1421 return construct(arguments, sizeof...(Args));
1422 }
1423
1429 [[nodiscard]] meta_any from_void(void *element) const {
1430 return (element && node.from_void) ? node.from_void(*ctx, element, nullptr) : meta_any{meta_ctx_arg, *ctx};
1431 }
1432
1434 [[nodiscard]] meta_any from_void(const void *element) const {
1435 return (element && node.from_void) ? node.from_void(*ctx, nullptr, element) : meta_any{meta_ctx_arg, *ctx};
1436 }
1437
1450 meta_any invoke(const id_type id, meta_handle instance, meta_any *const args, const size_type sz) const {
1451 if(node.details) {
1452 if(auto it = node.details->func.find(id); it != node.details->func.cend()) {
1453 if(const auto *candidate = lookup(args, sz, instance && (instance->data() == nullptr), [curr = &it->second]() mutable { return curr ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) {
1454 return candidate->invoke(*ctx, meta_handle{*ctx, std::move(instance)}, args);
1455 }
1456 }
1457 }
1458
1459 for(auto &&curr: base()) {
1460 if(auto elem = curr.second.invoke(id, *instance.operator->(), args, sz); elem) {
1461 return elem;
1462 }
1463 }
1464
1465 return meta_any{meta_ctx_arg, *ctx};
1466 }
1467
1476 template<typename... Args>
1477 meta_any invoke(const id_type id, meta_handle instance, Args &&...args) const {
1478 meta_any arguments[sizeof...(Args) + !sizeof...(Args)]{{*ctx, std::forward<Args>(args)}...};
1479 return invoke(id, std::move(instance), arguments, sizeof...(Args));
1480 }
1481
1490 template<typename Type>
1491 bool set(const id_type id, meta_handle instance, Type &&value) const {
1492 const auto candidate = data(id);
1493 return candidate && candidate.set(std::move(instance), std::forward<Type>(value));
1494 }
1495
1502 [[nodiscard]] meta_any get(const id_type id, meta_handle instance) const {
1503 const auto candidate = data(id);
1504 return candidate ? candidate.get(std::move(instance)) : meta_any{meta_ctx_arg, *ctx};
1505 }
1506
1511 [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_type_descriptor::prop)::const_iterator> prop() const noexcept {
1512 using range_type = meta_range<meta_prop, typename decltype(internal::meta_type_descriptor::prop)::const_iterator>;
1513 return node.details ? range_type{{*ctx, node.details->prop.cbegin()}, {*ctx, node.details->prop.cend()}} : range_type{};
1514 }
1515
1521 [[nodiscard]] meta_prop prop(const id_type key) const {
1522 const auto *elem = internal::look_for<&internal::meta_type_descriptor::prop>(internal::meta_context::from(*ctx), node, key);
1523 return elem ? meta_prop{*ctx, *elem} : meta_prop{};
1524 }
1525
1530 [[nodiscard]] explicit operator bool() const noexcept {
1531 return !(ctx == nullptr);
1532 }
1533
1535 [[nodiscard]] bool operator==(const meta_type &other) const noexcept {
1536 return (ctx == other.ctx) && ((!node.info && !other.node.info) || (node.info && other.node.info && *node.info == *other.node.info));
1537 }
1538
1539private:
1540 internal::meta_type_node node;
1541 const meta_ctx *ctx;
1542};
1543
1550[[nodiscard]] inline bool operator!=(const meta_type &lhs, const meta_type &rhs) noexcept {
1551 return !(lhs == rhs);
1552}
1553
1554[[nodiscard]] inline meta_type meta_any::type() const noexcept {
1555 return node.info ? meta_type{*ctx, node} : meta_type{};
1556}
1557
1558template<typename... Args>
1559meta_any meta_any::invoke(const id_type id, Args &&...args) const {
1560 return type().invoke(id, *this, std::forward<Args>(args)...);
1561}
1562
1563template<typename... Args>
1564meta_any meta_any::invoke(const id_type id, Args &&...args) {
1565 return type().invoke(id, *this, std::forward<Args>(args)...);
1566}
1567
1568template<typename Type>
1569bool meta_any::set(const id_type id, Type &&value) {
1570 return type().set(id, *this, std::forward<Type>(value));
1571}
1572
1573[[nodiscard]] inline meta_any meta_any::get(const id_type id) const {
1574 return type().get(id, *this);
1575}
1576
1577[[nodiscard]] inline meta_any meta_any::get(const id_type id) {
1578 return type().get(id, *this);
1579}
1580
1581[[nodiscard]] inline meta_any meta_any::allow_cast(const meta_type &type) const {
1582 return internal::try_convert(internal::meta_context::from(*ctx), node, type.info(), type.is_arithmetic() || type.is_enum(), data(), [this, &type]([[maybe_unused]] const void *instance, auto &&...args) {
1583 if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<decltype(args)>>, internal::meta_type_node> || ...)) {
1584 return (args.from_void(*ctx, nullptr, instance), ...);
1585 } else if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<decltype(args)>>, internal::meta_conv_node> || ...)) {
1586 return (args.conv(*ctx, instance), ...);
1587 } else if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<decltype(args)>>, decltype(internal::meta_type_node::conversion_helper)> || ...)) {
1588 // exploits the fact that arithmetic types and enums are also default constructible
1589 auto other = type.construct();
1590 const auto value = (args(nullptr, instance), ...);
1591 other.node.conversion_helper(other.data(), &value);
1592 return other;
1593 } else {
1594 // forwards to force a compile-time error in case of available arguments
1595 return meta_any{meta_ctx_arg, *ctx, std::forward<decltype(args)>(args)...};
1596 }
1597 });
1598}
1599
1600inline bool meta_any::assign(const meta_any &other) {
1601 auto value = other.allow_cast({*ctx, node});
1602 return value && storage.assign(value.storage);
1603}
1604
1605inline bool meta_any::assign(meta_any &&other) {
1606 if(*node.info == *other.node.info) {
1607 return storage.assign(std::move(other.storage));
1608 }
1609
1610 return assign(std::as_const(other));
1611}
1612
1613[[nodiscard]] inline meta_type meta_data::type() const noexcept {
1614 return meta_type{*ctx, node->type(internal::meta_context::from(*ctx))};
1615}
1616
1617[[nodiscard]] inline meta_type meta_data::arg(const size_type index) const noexcept {
1618 return index < arity() ? node->arg(*ctx, index) : meta_type{};
1619}
1620
1621[[nodiscard]] inline meta_type meta_func::ret() const noexcept {
1622 return meta_type{*ctx, node->ret(internal::meta_context::from(*ctx))};
1623}
1624
1625[[nodiscard]] inline meta_type meta_func::arg(const size_type index) const noexcept {
1626 return index < arity() ? node->arg(*ctx, index) : meta_type{};
1627}
1628
1630class meta_sequence_container::meta_iterator final {
1631 using vtable_type = void(const void *, const std::ptrdiff_t, meta_any *);
1632
1633 template<typename It>
1634 static void basic_vtable(const void *value, const std::ptrdiff_t offset, meta_any *other) {
1635 const auto &it = *static_cast<const It *>(value);
1636 other ? other->emplace<decltype(*it)>(*it) : std::advance(const_cast<It &>(it), offset);
1637 }
1638
1639public:
1640 using difference_type = std::ptrdiff_t;
1641 using value_type = meta_any;
1642 using pointer = input_iterator_pointer<value_type>;
1643 using reference = value_type;
1644 using iterator_category = std::input_iterator_tag;
1645 using iterator_concept = std::bidirectional_iterator_tag;
1646
1647 meta_iterator() noexcept
1648 : meta_iterator{locator<meta_ctx>::value_or()} {}
1649
1650 meta_iterator(const meta_ctx &area) noexcept
1651 : ctx{&area} {}
1652
1653 template<typename It>
1654 meta_iterator(const meta_ctx &area, It iter) noexcept
1655 : ctx{&area},
1656 vtable{&basic_vtable<It>},
1657 handle{iter} {}
1658
1659 meta_iterator &operator++() noexcept {
1660 vtable(handle.data(), 1, nullptr);
1661 return *this;
1662 }
1663
1664 meta_iterator operator++(int value) noexcept {
1665 meta_iterator orig = *this;
1666 vtable(handle.data(), ++value, nullptr);
1667 return orig;
1668 }
1669
1670 meta_iterator &operator--() noexcept {
1671 vtable(handle.data(), -1, nullptr);
1672 return *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 static_cast<bool>(handle);
1693 }
1694
1695 [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
1696 return handle == other.handle;
1697 }
1698
1699 [[nodiscard]] bool operator!=(const meta_iterator &other) const noexcept {
1700 return !(*this == other);
1701 }
1702
1703 [[nodiscard]] const any &base() const noexcept {
1704 return handle;
1705 }
1706
1707private:
1708 const meta_ctx *ctx{};
1709 vtable_type *vtable{};
1710 any handle{};
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 difference_type = std::ptrdiff_t;
1732 using value_type = std::pair<meta_any, meta_any>;
1733 using pointer = input_iterator_pointer<value_type>;
1734 using reference = value_type;
1735 using iterator_category = std::input_iterator_tag;
1736 using iterator_concept = std::forward_iterator_tag;
1737
1738 meta_iterator() noexcept
1739 : meta_iterator{locator<meta_ctx>::value_or()} {}
1740
1741 meta_iterator(const meta_ctx &area) noexcept
1742 : ctx{&area} {}
1743
1744 template<bool KeyOnly, typename It>
1745 meta_iterator(const meta_ctx &area, std::bool_constant<KeyOnly>, It iter) noexcept
1746 : ctx{&area},
1747 vtable{&basic_vtable<KeyOnly, It>},
1748 handle{iter} {}
1749
1750 meta_iterator &operator++() noexcept {
1751 vtable(handle.data(), nullptr);
1752 return *this;
1753 }
1754
1755 meta_iterator operator++(int) noexcept {
1756 meta_iterator orig = *this;
1757 vtable(handle.data(), nullptr);
1758 return orig;
1759 }
1760
1761 [[nodiscard]] reference operator*() const {
1762 reference other{{meta_ctx_arg, *ctx}, {meta_ctx_arg, *ctx}};
1763 vtable(handle.data(), &other);
1764 return other;
1765 }
1766
1767 [[nodiscard]] pointer operator->() const {
1768 return operator*();
1769 }
1770
1771 [[nodiscard]] explicit operator bool() const noexcept {
1772 return static_cast<bool>(handle);
1773 }
1774
1775 [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
1776 return handle == other.handle;
1777 }
1778
1779 [[nodiscard]] bool operator!=(const meta_iterator &other) const noexcept {
1780 return !(*this == other);
1781 }
1782
1783private:
1784 const meta_ctx *ctx{};
1785 vtable_type *vtable{};
1786 any handle{};
1787};
1794[[nodiscard]] inline meta_type meta_sequence_container::value_type() const noexcept {
1795 return value_type_node ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1796}
1797
1803 return size_fn(data);
1804}
1805
1812 return !const_only && resize_fn(const_cast<void *>(data), sz);
1813}
1814
1820 return !const_only && clear_fn(const_cast<void *>(data));
1821}
1822
1829 return !const_only && reserve_fn(const_cast<void *>(data), sz);
1830}
1831
1837 return begin_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data);
1838}
1839
1845 return end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data);
1846}
1847
1855 // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
1856 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))}))) {
1857 const bool is_value_type = (value.type().info() == *vtype.info);
1858 return insert_fn(*ctx, const_cast<void *>(data), is_value_type ? std::as_const(value).data() : nullptr, is_value_type ? nullptr : std::as_const(value).data(), it);
1859 }
1860
1861 return iterator{*ctx};
1862}
1863
1870 return const_only ? iterator{*ctx} : erase_fn(*ctx, const_cast<void *>(data), it);
1871}
1872
1880 auto it = begin();
1881 it.operator++(static_cast<int>(pos) - 1);
1882 return *it;
1883}
1884
1889[[nodiscard]] inline meta_sequence_container::operator bool() const noexcept {
1890 return (data != nullptr);
1891}
1892
1897[[deprecated("use mapped_type() instead")]] [[nodiscard]] inline bool meta_associative_container::key_only() const noexcept {
1898 return (mapped_type_node == nullptr);
1899}
1900
1905[[nodiscard]] inline meta_type meta_associative_container::key_type() const noexcept {
1906 return key_type_node ? meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1907}
1908
1913[[nodiscard]] inline meta_type meta_associative_container::mapped_type() const noexcept {
1914 return mapped_type_node ? meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1915}
1916
1918[[nodiscard]] inline meta_type meta_associative_container::value_type() const noexcept {
1919 return value_type_node ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1920}
1921
1924 return size_fn(data);
1925}
1926
1929 return !const_only && clear_fn(const_cast<void *>(data));
1930}
1931
1934 return !const_only && reserve_fn(const_cast<void *>(data), sz);
1935}
1936
1939 return begin_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data);
1940}
1941
1944 return end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data);
1945}
1946
1954 return !const_only && key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})
1955 && (!mapped_type_node || value.allow_cast(meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))}))
1956 && insert_fn(const_cast<void *>(data), std::as_const(key).data(), std::as_const(value).data());
1957}
1958
1965 return (!const_only && key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})) ? erase_fn(const_cast<void *>(data), std::as_const(key).data()) : 0u;
1966}
1967
1974 return key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))}) ? find_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, std::as_const(key).data()) : iterator{*ctx};
1975}
1976
1981[[nodiscard]] inline meta_associative_container::operator bool() const noexcept {
1982 return (data != nullptr);
1983}
1984
1985} // namespace entt
1986
1987#endif
basic_any as_ref() noexcept
Aliasing constructor.
Definition any.hpp:390
pointer data() const noexcept
Direct access to the internal packed array.
deletion_policy policy() const noexcept
Returns the deletion policy of a sparse set.
Basic storage implementation.
Definition storage.hpp:229
value_type & emplace(const entity_type entt, Args &&...args)
Assigns an entity to a storage and constructs its object.
Definition storage.hpp:663
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:78
Opaque wrapper for values of any type.
Definition meta.hpp:181
bool assign(const meta_any &other)
Assigns a value to the contained object without replacing it.
Definition meta.hpp:1600
meta_any & operator=(const meta_any &other)
Copy assignment operator.
Definition meta.hpp:335
meta_associative_container as_associative_container() noexcept
Returns an associative container proxy.
Definition meta.hpp:557
meta_type type() const noexcept
Returns the object type if any, type_id<void>() otherwise.
Definition meta.hpp:1554
meta_any(const meta_ctx &area, const meta_any &other)
Context aware copy constructor.
Definition meta.hpp:292
meta_any(meta_ctx_arg_t, const meta_ctx &area) noexcept
Context aware constructor.
Definition meta.hpp:238
meta_any(meta_any &&other) noexcept
Move constructor.
Definition meta.hpp:319
void * data() noexcept
Returns an opaque pointer to the contained instance.
Definition meta.hpp:380
meta_any(std::in_place_type_t< Type >, Args &&...args)
Constructs a wrapper by directly initializing the new object.
Definition meta.hpp:251
meta_any as_ref() noexcept
Aliasing constructor.
Definition meta.hpp:600
const Type * try_cast() const
Tries to cast an instance to a given type.
Definition meta.hpp:424
void emplace(Args &&...args)
Replaces the contained object by creating a new instance directly.
Definition meta.hpp:515
meta_any(const meta_ctx &area, meta_any &&other)
Context aware move constructor.
Definition meta.hpp:303
Type cast()
Tries to cast an instance to a given type.
Definition meta.hpp:454
meta_sequence_container as_sequence_container() noexcept
Returns a sequence container proxy.
Definition meta.hpp:540
Type * try_cast()
Tries to cast an instance to a given type.
Definition meta.hpp:431
meta_associative_container as_associative_container() const noexcept
Returns an associative container proxy.
Definition meta.hpp:564
meta_any_policy policy() const noexcept
Returns the current mode of a meta any object.
Definition meta.hpp:618
meta_any(const meta_any &other)=default
Copy constructor.
meta_any operator*() const noexcept
Indirection operator for dereferencing opaque objects.
Definition meta.hpp:575
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:1581
meta_any get(const id_type id) const
Gets the value of a given variable.
Definition meta.hpp:1573
meta_any(const meta_ctx &area, Type &&value)
Constructs a wrapper from a given value.
Definition meta.hpp:284
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:262
meta_any as_ref() const noexcept
Aliasing constructor.
Definition meta.hpp:605
meta_any allow_cast() const
Converts an object in such a way that a given cast becomes viable.
Definition meta.hpp:493
std::enable_if_t<!std::is_same_v< std::decay_t< Type >, meta_any >, meta_any & > operator=(Type &&value)
Value assignment operator.
Definition meta.hpp:366
meta_any(Type &&value)
Constructs a wrapper from a given value.
Definition meta.hpp:274
~meta_any()
Frees the internal storage, whatever it means.
Definition meta.hpp:326
Type cast() const
Tries to cast an instance to a given type.
Definition meta.hpp:446
void reset()
Destroys contained object.
Definition meta.hpp:529
bool set(const id_type id, Type &&value)
Sets the value of a given variable.
Definition meta.hpp:1569
meta_any invoke(const id_type id, Args &&...args) const
Invokes the underlying function, if possible.
Definition meta.hpp:1559
meta_any() noexcept
Definition meta.hpp:231
meta_sequence_container as_sequence_container() const noexcept
Returns a sequence container proxy.
Definition meta.hpp:547
bool operator==(const meta_any &other) const noexcept
Checks if two wrappers differ in their content.
Definition meta.hpp:590
const void * data() const noexcept
Returns an opaque pointer to the contained instance.
Definition meta.hpp:375
bool operator!=(const meta_any &other) const noexcept
Checks if two wrappers differ in their content.
Definition meta.hpp:595
bool allow_cast()
Converts an object in such a way that a given cast becomes viable.
Definition meta.hpp:508
bool allow_cast(const meta_type &type)
Converts an object in such a way that a given cast becomes viable.
Definition meta.hpp:474
meta_any & operator=(meta_any &&other) noexcept
Move assignment operator.
Definition meta.hpp:349
bool owner() const noexcept
Returns true if a wrapper owns its object, false otherwise.
Definition meta.hpp:610
Proxy object for associative containers.
Definition meta.hpp:100
meta_associative_container(const meta_ctx &area) noexcept
Context aware constructor.
Definition meta.hpp:117
size_type erase(meta_any)
Removes the specified element from a container.
Definition meta.hpp:1964
iterator find(meta_any)
Returns an iterator to the element with a given key, if any.
Definition meta.hpp:1973
bool insert(meta_any, meta_any)
Inserts a key-only or key/value element into a container.
Definition meta.hpp:1953
meta_associative_container() noexcept
Default constructor.
Definition meta.hpp:110
iterator end()
Returns an iterator that is past the last element of a container.
Definition meta.hpp:1943
bool key_only() const noexcept
Returns true if a container is also key-only, false otherwise.
Definition meta.hpp:1897
bool reserve(const size_type)
Reserves storage for at least the given number of elements.
Definition meta.hpp:1933
iterator begin()
Returns an iterator to the first element of a container.
Definition meta.hpp:1938
size_type size() const noexcept
Returns the size of a container.
Definition meta.hpp:1923
meta_type mapped_type() const noexcept
Returns the meta mapped type of a container.
Definition meta.hpp:1913
std::size_t size_type
Unsigned integer type.
Definition meta.hpp:105
meta_iterator iterator
Meta iterator type.
Definition meta.hpp:107
meta_type value_type() const noexcept
Returns the meta value type of a container.
Definition meta.hpp:1918
void rebind(Type &instance) noexcept
Rebinds a proxy object to an associative container type.
Definition meta.hpp:126
meta_type key_type() const noexcept
Returns the meta key type of a container.
Definition meta.hpp:1905
bool clear()
Clears the content of a container.
Definition meta.hpp:1928
Disambiguation tag for constructors and the like.
Definition context.hpp:28
Opaque meta context type.
Definition context.hpp:34
Proxy object for sequence containers.
Definition meta.hpp:30
meta_sequence_container() noexcept
Default constructor.
Definition meta.hpp:40
meta_type value_type() const noexcept
Returns the meta value type of a container.
Definition meta.hpp:1794
iterator end()
Returns an iterator that is past the last element of a container.
Definition meta.hpp:1844
bool reserve(const size_type)
Reserves storage for at least the given number of elements.
Definition meta.hpp:1828
meta_any operator[](const size_type)
Returns a reference to the element at a given location of a container (no bounds checking is performe...
Definition meta.hpp:1879
void rebind(Type &instance) noexcept
Rebinds a proxy object to a sequence container type.
Definition meta.hpp:56
bool resize(const size_type)
Resizes a container to contain a given number of elements.
Definition meta.hpp:1811
meta_iterator iterator
Meta iterator type.
Definition meta.hpp:37
std::size_t size_type
Unsigned integer type.
Definition meta.hpp:35
iterator erase(iterator)
Removes a given element from a container.
Definition meta.hpp:1869
iterator insert(iterator, meta_any)
Inserts an element at a specified location of a container.
Definition meta.hpp:1854
meta_sequence_container(const meta_ctx &area) noexcept
Context aware constructor.
Definition meta.hpp:47
size_type size() const noexcept
Returns the size of a container.
Definition meta.hpp:1802
iterator begin()
Returns an iterator to the first element of a container.
Definition meta.hpp:1836
bool clear()
Clears the content of a container.
Definition meta.hpp:1819
Opaque wrapper for types.
Definition meta.hpp:1092
meta_type(const meta_ctx &area, const internal::meta_type_node &curr) noexcept
Context aware constructor for meta objects.
Definition meta.hpp:1158
bool is_pointer() const noexcept
Checks whether a type refers to a pointer or not.
Definition meta.hpp:1247
bool is_arithmetic() const noexcept
Checks whether a type refers to an arithmetic type or not.
Definition meta.hpp:1199
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:1370
id_type id() const noexcept
Returns the identifier assigned to a type.
Definition meta.hpp:1182
meta_func func(const id_type id) const
Lookup utility for meta functions (bases are also visited).
Definition meta.hpp:1383
meta_type remove_pointer() const noexcept
Provides the type for which the pointer is defined.
Definition meta.hpp:1256
meta_any construct(Args &&...args) const
Creates an instance of the underlying type, if possible.
Definition meta.hpp:1419
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:1315
bool is_array() const noexcept
Checks whether a type refers to an array type or not.
Definition meta.hpp:1223
meta_range< meta_prop, typename decltype(internal::meta_type_descriptor::prop)::const_iterator > prop() const noexcept
Returns a range to visit registered top-level meta properties.
Definition meta.hpp:1511
meta_data data(const id_type id) const
Lookup utility for meta data (bases are also visited).
Definition meta.hpp:1361
bool is_class() const noexcept
Checks whether a type refers to a class or not.
Definition meta.hpp:1239
bool set(const id_type id, meta_handle instance, Type &&value) const
Sets the value of a given variable.
Definition meta.hpp:1491
typename internal::meta_type_node::size_type size_type
Unsigned integer type.
Definition meta.hpp:1146
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:1351
meta_prop prop(const id_type key) const
Lookup utility for meta properties (bases are also visited).
Definition meta.hpp:1521
meta_any invoke(const id_type id, meta_handle instance, Args &&...args) const
Invokes a function given an identifier, if possible.
Definition meta.hpp:1477
bool can_convert(const meta_type &other) const noexcept
Checks if a type supports conversion it to another type.
Definition meta.hpp:1334
bool is_signed() const noexcept
Checks whether a type refers to a signed type or not.
Definition meta.hpp:1215
bool is_enum() const noexcept
Checks whether a type refers to an enum or not.
Definition meta.hpp:1231
bool can_cast(const meta_type &other) const noexcept
Checks if a type supports direct casting to another type.
Definition meta.hpp:1324
bool operator==(const meta_type &other) const noexcept
Checks if two objects refer to the same type.
Definition meta.hpp:1535
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:1342
meta_type() noexcept
Default constructor.
Definition meta.hpp:1149
bool is_pointer_like() const noexcept
Checks whether a type is a pointer-like type or not.
Definition meta.hpp:1264
meta_any get(const id_type id, meta_handle instance) const
Gets the value of a given variable.
Definition meta.hpp:1502
meta_any construct(meta_any *const args, const size_type sz) const
Creates an instance of the underlying type, if possible.
Definition meta.hpp:1398
bool is_integral() const noexcept
Checks whether a type refers to an integral type or not.
Definition meta.hpp:1207
meta_any from_void(const void *element) const
Wraps an opaque element of the underlying type.
Definition meta.hpp:1434
meta_type template_type() const noexcept
Returns a tag for the class template of the underlying type.
Definition meta.hpp:1306
meta_type(const meta_ctx &area, const internal::meta_base_node &curr) noexcept
Context aware constructor for meta objects.
Definition meta.hpp:1167
const type_info & info() const noexcept
Returns the type info object of the underlying type.
Definition meta.hpp:1174
bool is_template_specialization() const noexcept
Checks whether a type refers to a recognized class template specialization or not.
Definition meta.hpp:1290
meta_any invoke(const id_type id, meta_handle instance, meta_any *const args, const size_type sz) const
Invokes a function given an identifier, if possible.
Definition meta.hpp:1450
bool is_associative_container() const noexcept
Checks whether a type refers to an associative container or not.
Definition meta.hpp:1280
size_type template_arity() const noexcept
Returns the number of template arguments.
Definition meta.hpp:1298
meta_any from_void(void *element) const
Wraps an opaque element of the underlying type.
Definition meta.hpp:1429
size_type size_of() const noexcept
Returns the size of the underlying type if known.
Definition meta.hpp:1190
bool is_sequence_container() const noexcept
Checks whether a type refers to a sequence container or not.
Definition meta.hpp:1272
EnTT default namespace.
Definition dense_map.hpp:21
std::uint32_t id_type
Alias declaration for type identifiers.
Definition fwd.hpp:13
basic_handle< registry > handle
Alias declaration for the most common use case.
Definition fwd.hpp:91
basic_any<> any
Alias declaration for the most common use case.
Definition fwd.hpp:16
constexpr get_t< Type... > get
Variable template for lists of observed components.
Definition fwd.hpp:157
meta_type resolve() noexcept
Returns the meta type associated with a given type.
Definition resolve.hpp:32
constexpr meta_ctx_arg_t meta_ctx_arg
Constant of type meta_context_arg_t used to disambiguate calls.
Definition context.hpp:31
meta_any forward_as_meta(const meta_ctx &ctx, Type &&value)
Forwards its argument and avoids copies for lvalue references.
Definition meta.hpp:637
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
any_policy
Possible modes of an any object.
Definition any.hpp:33
@ ref
Aliasing mode, the object points to a non-const element.
@ cref
Const aliasing mode, the object points to a const element.
@ owner
Default mode, the object owns the contained element.
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
Fake ADL based lookup function for meta pointer-like types.
static decltype(auto) dereference(const Type &value)
Uses the default ADL based lookup method to resolve the call.
Utility class to create an iterable object from a pair of iterators.
Definition iterator.hpp:141
Traits class template to be specialized to enable support for meta associative containers.
Opaque wrapper for data members.
Definition meta.hpp:837
bool is_const() const noexcept
Indicates whether a data member is constant or not.
Definition meta.hpp:867
typename internal::meta_data_node::size_type size_type
Unsigned integer type.
Definition meta.hpp:839
meta_type arg(const size_type index) const noexcept
Returns the type accepted by the i-th setter.
Definition meta.hpp:1617
meta_prop prop(const id_type key) const
Lookup utility for meta properties.
Definition meta.hpp:923
meta_any get(meta_handle instance) const
Gets the value of a given variable.
Definition meta.hpp:899
size_type arity() const noexcept
Returns the number of setters available.
Definition meta.hpp:859
meta_range< meta_prop, typename decltype(internal::meta_data_node::prop)::const_iterator > prop() const noexcept
Returns a range to visit registered meta properties.
Definition meta.hpp:914
bool operator==(const meta_data &other) const noexcept
Checks if two objects refer to the same type.
Definition meta.hpp:937
bool set(meta_handle instance, Type &&value) const
Sets the value of a given variable.
Definition meta.hpp:890
meta_type type() const noexcept
Returns the object type if any, type_id<void>() otherwise.
Definition meta.hpp:1613
bool is_static() const noexcept
Indicates whether a data member is static or not.
Definition meta.hpp:875
meta_data(const meta_ctx &area, const internal::meta_data_node &curr) noexcept
Context aware constructor for meta objects.
Definition meta.hpp:851
meta_data() noexcept
Default constructor.
Definition meta.hpp:842
Opaque wrapper for member functions.
Definition meta.hpp:957
bool is_static() const noexcept
Indicates whether a member function is static or not.
Definition meta.hpp:995
meta_func() noexcept
Default constructor.
Definition meta.hpp:962
typename internal::meta_func_node::size_type size_type
Unsigned integer type.
Definition meta.hpp:959
meta_type ret() const noexcept
Returns the return type of a member function.
Definition meta.hpp:1621
bool operator==(const meta_func &other) const noexcept
Checks if two objects refer to the same type.
Definition meta.hpp:1072
meta_func(const meta_ctx &area, const internal::meta_func_node &curr) noexcept
Context aware constructor for meta objects.
Definition meta.hpp:971
meta_prop prop(const id_type key) const
Lookup utility for meta properties.
Definition meta.hpp:1050
meta_range< meta_prop, typename decltype(internal::meta_func_node::prop)::const_iterator > prop() const noexcept
Returns a range to visit registered meta properties.
Definition meta.hpp:1041
meta_any invoke(meta_handle instance, meta_any *const args, const size_type sz) const
Invokes the underlying function, if possible.
Definition meta.hpp:1023
bool is_const() const noexcept
Indicates whether a member function is constant or not.
Definition meta.hpp:987
meta_any invoke(meta_handle instance, Args &&...args) const
Invokes the underlying function, if possible.
Definition meta.hpp:1035
meta_func next() const
Returns the next overload of a given function, if any.
Definition meta.hpp:1059
size_type arity() const noexcept
Returns the number of arguments accepted by a member function.
Definition meta.hpp:979
meta_type arg(const size_type index) const noexcept
Returns the type of the i-th argument of a member function.
Definition meta.hpp:1625
Opaque pointers to instances of any type.
Definition meta.hpp:658
bool operator!=(const meta_handle &other) const noexcept
Checks if two wrappers differ in their content.
Definition meta.hpp:751
meta_handle(Type &value) noexcept
Creates a handle that points to an unmanaged object.
Definition meta.hpp:700
meta_handle() noexcept
Definition meta.hpp:660
meta_handle & operator=(const meta_handle &)=delete
Default copy assignment operator, deleted on purpose.
meta_handle(meta_ctx_arg_t, const meta_ctx &area) noexcept
Context aware constructor.
Definition meta.hpp:667
meta_handle(const meta_ctx &ctx, Type &value) noexcept
Creates a handle that points to an unmanaged object.
Definition meta.hpp:691
meta_handle(const meta_any &value) noexcept
Creates a handle that points to an unmanaged object.
Definition meta.hpp:681
meta_handle(const meta_ctx &area, const meta_handle &other)
Context aware copy constructor.
Definition meta.hpp:708
bool operator==(const meta_handle &other) const noexcept
Checks if two wrappers differ in their content.
Definition meta.hpp:746
meta_handle(meta_handle &&)=default
Default move constructor.
meta_handle(const meta_ctx &area, meta_handle &&other)
Context aware move constructor.
Definition meta.hpp:716
const meta_any * operator->() const
Access operator for accessing the contained opaque object.
Definition meta.hpp:764
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:759
meta_handle(meta_any &value) noexcept
Creates a handle that points to an unmanaged object.
Definition meta.hpp:674
Opaque wrapper for properties of any type.
Definition meta.hpp:773
meta_prop() noexcept
Default constructor.
Definition meta.hpp:775
meta_any value()
Returns the stored value by reference.
Definition meta.hpp:800
meta_prop(const meta_ctx &area, const internal::meta_prop_node &curr) noexcept
Context aware constructor for meta objects.
Definition meta.hpp:784
meta_any value() const
Returns the stored value by const reference.
Definition meta.hpp:792
bool operator==(const meta_prop &other) const noexcept
Checks if two objects refer to the same type.
Definition meta.hpp:817
Traits class template to be specialized to enable support for meta sequence containers.
Implementation specific information about a type.
constexpr id_type hash() const noexcept
Type hash.