EnTT 3.15.0
All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
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_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::begin},
60 end_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::end},
61 insert_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::insert},
62 erase_fn{meta_sequence_container_traits<std::remove_const_t<Type>>::erase},
63 const_only{std::is_const_v<Type>} {}
64
65 [[nodiscard]] inline meta_type value_type() const noexcept;
66 [[nodiscard]] inline size_type size() const noexcept;
67 inline bool resize(size_type);
68 inline bool clear();
69 inline bool reserve(size_type);
70 [[nodiscard]] inline iterator begin();
71 [[nodiscard]] inline iterator end();
72 inline iterator insert(const iterator &, meta_any);
73 inline iterator erase(const iterator &);
74 [[nodiscard]] inline meta_any operator[](size_type);
75 [[nodiscard]] inline explicit operator bool() const noexcept;
76
77private:
78 const meta_ctx *ctx{};
79 const void *data{};
80 internal::meta_type_node (*value_type_node)(const internal::meta_context &){};
81 internal::meta_type_node (*const_reference_node)(const internal::meta_context &){};
82 size_type (*size_fn)(const void *){};
83 bool (*clear_fn)(void *){};
84 bool (*reserve_fn)(void *, const size_type){};
85 bool (*resize_fn)(void *, const size_type){};
86 iterator (*begin_fn)(const meta_ctx &, void *, const void *){};
87 iterator (*end_fn)(const meta_ctx &, void *, const void *){};
88 iterator (*insert_fn)(const meta_ctx &, void *, const void *, const void *, const iterator &){};
89 iterator (*erase_fn)(const meta_ctx &, void *, const iterator &){};
90 bool const_only{};
91};
92
95 class meta_iterator;
96
97public:
99 using size_type = std::size_t;
101 using iterator = meta_iterator;
102
105
112 template<typename Type>
113 meta_associative_container(const meta_ctx &area, Type &instance) noexcept
114 : ctx{&area},
115 data{&instance},
116 key_type_node{&internal::resolve<typename Type::key_type>},
117 value_type_node{&internal::resolve<typename Type::value_type>},
118 size_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::size},
119 clear_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::clear},
120 reserve_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::reserve},
121 begin_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::begin},
122 end_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::end},
123 insert_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::insert},
124 erase_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::erase},
125 find_fn{&meta_associative_container_traits<std::remove_const_t<Type>>::find},
126 const_only{std::is_const_v<Type>} {
127 if constexpr(!meta_associative_container_traits<std::remove_const_t<Type>>::key_only) {
128 mapped_type_node = &internal::resolve<typename Type::mapped_type>;
129 }
130 }
131
132 [[nodiscard]] inline meta_type key_type() const noexcept;
133 [[nodiscard]] inline meta_type mapped_type() const noexcept;
134 [[nodiscard]] inline meta_type value_type() const noexcept;
135 [[nodiscard]] inline size_type size() const noexcept;
136 inline bool clear();
137 inline bool reserve(size_type);
138 [[nodiscard]] inline iterator begin();
139 [[nodiscard]] inline iterator end();
140 inline bool insert(meta_any, meta_any);
141 inline size_type erase(meta_any);
142 [[nodiscard]] inline iterator find(meta_any);
143 [[nodiscard]] inline explicit operator bool() const noexcept;
144
145private:
146 const meta_ctx *ctx{};
147 const void *data{};
148 internal::meta_type_node (*key_type_node)(const internal::meta_context &){};
149 internal::meta_type_node (*mapped_type_node)(const internal::meta_context &){};
150 internal::meta_type_node (*value_type_node)(const internal::meta_context &){};
151 size_type (*size_fn)(const void *){};
152 bool (*clear_fn)(void *){};
153 bool (*reserve_fn)(void *, const size_type){};
154 iterator (*begin_fn)(const meta_ctx &, void *, const void *){};
155 iterator (*end_fn)(const meta_ctx &, void *, const void *){};
156 bool (*insert_fn)(void *, const void *, const void *){};
157 size_type (*erase_fn)(void *, const void *){};
158 iterator (*find_fn)(const meta_ctx &, void *, const void *, const void *){};
159 bool const_only{};
160};
161
163using meta_any_policy [[deprecated("use any_policy instead")]] = any_policy;
164
166class meta_any {
167 using vtable_type = void(const internal::meta_traits op, const meta_ctx &, const void *, void *);
168
169 template<typename Type>
170 static void basic_vtable([[maybe_unused]] const internal::meta_traits req, [[maybe_unused]] const meta_ctx &area, [[maybe_unused]] const void *value, [[maybe_unused]] void *other) {
171 static_assert(std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>, "Invalid type");
172
173 if constexpr(is_meta_pointer_like_v<Type>) {
174 if(!!(req & internal::meta_traits::is_pointer_like)) {
175 if constexpr(std::is_function_v<typename std::pointer_traits<Type>::element_type>) {
176 static_cast<meta_any *>(other)->emplace<Type>(*static_cast<const Type *>(value));
177 } else if constexpr(!std::is_void_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) {
178 using in_place_type = decltype(adl_meta_pointer_like<Type>::dereference(std::declval<const Type &>()));
179
180 if constexpr(std::is_constructible_v<bool, Type>) {
181 if(const auto &pointer_like = *static_cast<const Type *>(value); pointer_like) {
182 static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(pointer_like));
183 }
184 } else {
185 static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(*static_cast<const Type *>(value)));
186 }
187 }
188 }
189 }
190
192 if(!!(req & internal::meta_traits::is_sequence_container)) {
193 // NOLINTNEXTLINE(bugprone-casting-through-void)
194 *static_cast<meta_sequence_container *>(other) = !!(req & internal::meta_traits::is_const) ? meta_sequence_container{area, *static_cast<const Type *>(value)} : meta_sequence_container{area, *static_cast<Type *>(const_cast<void *>(value))};
195 }
196 }
197
199 if(!!(req & internal::meta_traits::is_associative_container)) {
200 // NOLINTNEXTLINE(bugprone-casting-through-void)
201 *static_cast<meta_associative_container *>(other) = !!(req & internal::meta_traits::is_const) ? meta_associative_container{area, *static_cast<const Type *>(value)} : meta_associative_container{area, *static_cast<Type *>(const_cast<void *>(value))};
202 }
203 }
204 }
205
206 void release() {
207 if(storage.owner() && (node.dtor.dtor != nullptr)) {
208 node.dtor.dtor(storage.data());
209 }
210 }
211
212 meta_any(const meta_any &other, any ref) noexcept
213 : storage{std::move(ref)},
214 ctx{other.ctx} {
215 if(storage || !other.storage) {
216 node = other.node;
217 vtable = other.vtable;
218 }
219 }
220
221public:
223 meta_any() = default;
224
230 : ctx{&area} {}
231
238 template<typename Type, typename... Args>
239 explicit meta_any(std::in_place_type_t<Type>, Args &&...args)
240 : meta_any{locator<meta_ctx>::value_or(), std::in_place_type<Type>, std::forward<Args>(args)...} {}
241
249 template<typename Type, typename... Args>
250 explicit meta_any(const meta_ctx &area, std::in_place_type_t<Type>, Args &&...args)
251 : storage{std::in_place_type<Type>, std::forward<Args>(args)...},
252 ctx{&area},
253 node{internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx))},
254 vtable{&basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>} {}
255
261 template<typename Type>
262 explicit meta_any(std::in_place_t, Type *value)
263 : meta_any{locator<meta_ctx>::value_or(), std::in_place, value} {}
264
271 template<typename Type>
272 explicit meta_any(const meta_ctx &area, std::in_place_t, Type *value)
273 : storage{std::in_place, value},
274 ctx{&area} {
275 if(storage) {
276 node = internal::resolve<Type>(internal::meta_context::from(*ctx));
277 vtable = &basic_vtable<Type>;
278 }
279 }
280
286 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
287 meta_any(Type &&value)
288 : meta_any{locator<meta_ctx>::value_or(), std::forward<Type>(value)} {}
289
296 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
297 meta_any(const meta_ctx &area, Type &&value)
298 : meta_any{area, std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
299
305 meta_any(const meta_ctx &area, const meta_any &other)
306 : storage{other.storage},
307 ctx{&area},
308 node{(other.node.resolve != nullptr) ? other.node.resolve(internal::meta_context::from(*ctx)) : other.node},
309 vtable{other.vtable} {}
310
316 meta_any(const meta_ctx &area, meta_any &&other)
317 : storage{std::move(other.storage)},
318 ctx{&area},
319 node{(other.node.resolve != nullptr) ? std::exchange(other.node, internal::meta_type_node{}).resolve(internal::meta_context::from(*ctx)) : std::exchange(other.node, internal::meta_type_node{})},
320 vtable{std::exchange(other.vtable, nullptr)} {}
321
326 meta_any(const meta_any &other) = default;
327
332 meta_any(meta_any &&other) noexcept
333 : storage{std::move(other.storage)},
334 ctx{other.ctx},
335 node{std::exchange(other.node, internal::meta_type_node{})},
336 vtable{std::exchange(other.vtable, nullptr)} {}
337
340 release();
341 }
342
348 meta_any &operator=(const meta_any &other) {
349 if(this != &other) {
350 release();
351 storage = other.storage;
352 ctx = other.ctx;
353 node = other.node;
354 vtable = other.vtable;
355 }
356
357 return *this;
358 }
359
369 meta_any &operator=(meta_any &&other) noexcept {
370 reset();
371 storage = std::move(other.storage);
372 ctx = other.ctx;
373 node = std::exchange(other.node, internal::meta_type_node{});
374 vtable = std::exchange(other.vtable, nullptr);
375 return *this;
376 }
377
384 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
385 meta_any &operator=(Type &&value) {
386 emplace<std::decay_t<Type>>(std::forward<Type>(value));
387 return *this;
388 }
389
391 [[nodiscard]] inline meta_type type() const noexcept;
392
394 [[nodiscard]] [[deprecated("use ::base().data() instead")]] const void *data() const noexcept {
395 return storage.data();
396 }
397
399 [[nodiscard]] [[deprecated("no longer supported, use ::base().data() for const access")]] void *data() noexcept {
400 return storage.data();
401 }
402
410 template<typename... Args>
411 meta_any invoke(id_type id, Args &&...args) const;
412
414 template<typename... Args>
415 meta_any invoke(id_type id, Args &&...args);
416
424 template<typename Type>
425 bool set(id_type id, Type &&value);
426
432 [[nodiscard]] meta_any get(id_type id) const;
433
435 [[nodiscard]] meta_any get(id_type id);
436
442 template<typename Type>
443 [[nodiscard]] const Type *try_cast() const {
444 const auto &other = type_id<std::remove_cv_t<Type>>();
445 return static_cast<const Type *>(internal::try_cast(internal::meta_context::from(*ctx), node, other, storage.data()));
446 }
447
449 template<typename Type>
450 [[nodiscard]] Type *try_cast() {
451 if constexpr(std::is_const_v<Type>) {
452 return std::as_const(*this).try_cast<std::remove_const_t<Type>>();
453 } else {
454 const auto &other = type_id<Type>();
455 // NOLINTNEXTLINE(bugprone-casting-through-void)
456 return static_cast<Type *>(const_cast<void *>(internal::try_cast(internal::meta_context::from(*ctx), node, other, storage.data())));
457 }
458 }
459
465 template<typename Type>
466 [[nodiscard]] std::remove_const_t<Type> cast() const {
467 auto *const instance = try_cast<std::remove_reference_t<Type>>();
468 ENTT_ASSERT(instance, "Invalid instance");
469 return static_cast<Type>(*instance);
470 }
471
473 template<typename Type>
474 [[nodiscard]] std::remove_const_t<Type> cast() {
475 // forces const on non-reference types to make them work also with wrappers for const references
476 auto *const instance = try_cast<std::remove_reference_t<const Type>>();
477 ENTT_ASSERT(instance, "Invalid instance");
478 return static_cast<Type>(*instance);
479 }
480
487 [[nodiscard]] meta_any allow_cast(const meta_type &type) const;
488
494 [[nodiscard]] bool allow_cast(const meta_type &type) {
495 if(auto other = std::as_const(*this).allow_cast(type); other) {
496 if(other.storage.owner()) {
497 std::swap(*this, other);
498 }
499
500 return true;
501 }
502
503 return false;
504 }
505
512 template<typename Type>
513 [[nodiscard]] meta_any allow_cast() const {
514 if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
515 return meta_any{meta_ctx_arg, *ctx};
516 } else {
517 // also support early return for performance reasons
518 return ((node.info != nullptr) && (*node.info == entt::type_id<Type>())) ? as_ref() : allow_cast(meta_type{*ctx, internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx))});
519 }
520 }
521
527 template<typename Type>
528 [[nodiscard]] bool allow_cast() {
529 if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
530 return allow_cast<const std::remove_reference_t<Type> &>() && (storage.data() != nullptr);
531 } else {
532 // also support early return for performance reasons
533 return ((node.info != nullptr) && (*node.info == entt::type_id<Type>())) || allow_cast(meta_type{*ctx, internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx))});
534 }
535 }
536
538 template<typename Type, typename... Args>
539 void emplace(Args &&...args) {
540 release();
541 storage.emplace<Type>(std::forward<Args>(args)...);
542 node = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
543 vtable = &basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
544 }
545
547 bool assign(const meta_any &other);
548
550 bool assign(meta_any &&other);
551
553 void reset() {
554 release();
555 storage.reset();
556 node = {};
557 vtable = nullptr;
558 }
559
565 meta_sequence_container proxy = (storage.policy() == any_policy::cref) ? std::as_const(*this).as_sequence_container() : meta_sequence_container{};
566 if(!proxy && vtable != nullptr) { vtable(internal::meta_traits::is_sequence_container, *ctx, storage.data(), &proxy); }
567 return proxy;
568 }
569
571 [[nodiscard]] meta_sequence_container as_sequence_container() const noexcept {
573 if(vtable != nullptr) { vtable(internal::meta_traits::is_sequence_container | internal::meta_traits::is_const, *ctx, storage.data(), &proxy); }
574 return proxy;
575 }
576
582 meta_associative_container proxy = (storage.policy() == any_policy::cref) ? std::as_const(*this).as_associative_container() : meta_associative_container{};
583 if(!proxy && vtable != nullptr) { vtable(internal::meta_traits::is_associative_container, *ctx, storage.data(), &proxy); }
584 return proxy;
585 }
586
590 if(vtable != nullptr) { vtable(internal::meta_traits::is_associative_container | internal::meta_traits::is_const, *ctx, storage.data(), &proxy); }
591 return proxy;
592 }
593
599 [[nodiscard]] meta_any operator*() const noexcept {
600 meta_any ret{meta_ctx_arg, *ctx};
601 if(vtable != nullptr) { vtable(internal::meta_traits::is_pointer_like, *ctx, storage.data(), &ret); }
602 return ret;
603 }
604
609 [[nodiscard]] explicit operator bool() const noexcept {
610 return !(node.info == nullptr);
611 }
612
614 [[nodiscard]] bool operator==(const meta_any &other) const noexcept {
615 return (ctx == other.ctx) && (((node.info == nullptr) && (other.node.info == nullptr)) || ((node.info != nullptr) && (other.node.info != nullptr) && *node.info == *other.node.info && storage == other.storage));
616 }
617
619 [[nodiscard]] bool operator!=(const meta_any &other) const noexcept {
620 return !(*this == other);
621 }
622
624 [[nodiscard]] meta_any as_ref() noexcept {
625 return meta_any{*this, storage.as_ref()};
626 }
627
629 [[nodiscard]] meta_any as_ref() const noexcept {
630 return meta_any{*this, storage.as_ref()};
631 }
632
637 [[nodiscard]] [[deprecated("use ::base().policy() instead")]] any_policy policy() const noexcept {
638 return storage.policy();
639 }
640
645 [[nodiscard]] const any &base() const noexcept {
646 return storage;
647 }
648
653 [[nodiscard]] const meta_ctx &context() const noexcept {
654 return *ctx;
655 }
656
657private:
658 any storage;
660 internal::meta_type_node node{};
661 vtable_type *vtable{};
662};
663
671template<typename Type>
672[[nodiscard]] meta_any forward_as_meta(const meta_ctx &ctx, Type &&value) {
673 return meta_any{ctx, std::in_place_type<Type &&>, std::forward<Type>(value)};
674}
675
682template<typename Type>
683[[nodiscard]] meta_any forward_as_meta(Type &&value) {
684 return forward_as_meta(locator<meta_ctx>::value_or(), std::forward<Type>(value));
685}
686
690 meta_handle() = default;
691
697 : any{meta_ctx_arg, area} {}
698
704 : any{value.as_ref()} {}
705
710 meta_handle(const meta_any &value)
711 : any{value.as_ref()} {}
712
719 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
720 meta_handle(const meta_ctx &ctx, Type &value)
721 : any{ctx, std::in_place_type<Type &>, value} {}
722
728 template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
729 meta_handle(Type &value)
730 : any{std::in_place_type<Type &>, value} {}
731
737 meta_handle(const meta_ctx &area, const meta_handle &other)
738 : any{area, other.any} {}
739
745 meta_handle(const meta_ctx &area, meta_handle &&other)
746 : any{area, std::move(other.any)} {}
747
749 meta_handle(const meta_handle &) = delete;
750
753
755 ~meta_handle() = default;
756
762
768
773 [[nodiscard]] explicit operator bool() const noexcept {
774 return static_cast<bool>(any);
775 }
776
778 [[nodiscard]] bool operator==(const meta_handle &other) const noexcept {
779 return (any == other.any);
780 }
781
783 [[nodiscard]] bool operator!=(const meta_handle &other) const noexcept {
784 return !(*this == other);
785 }
786
791 [[nodiscard]] meta_any *operator->() {
792 return &any;
793 }
794
796 [[nodiscard]] const meta_any *operator->() const {
797 return &any;
798 }
799
800private:
802};
803
807 meta_custom() noexcept = default;
808
813 meta_custom(internal::meta_custom_node curr) noexcept
814 : node{std::move(curr)} {}
815
820 template<typename Type>
821 [[nodiscard]] operator Type *() const noexcept {
822 return (type_id<Type>().hash() == node.type) ? std::static_pointer_cast<Type>(node.value).get() : nullptr;
823 }
824
829 template<typename Type>
830 [[nodiscard]] operator Type &() const noexcept {
831 ENTT_ASSERT(type_id<Type>().hash() == node.type, "Invalid type");
832 return *std::static_pointer_cast<Type>(node.value);
833 }
834
835private:
836 internal::meta_custom_node node{};
837};
838
840struct meta_data {
842 using size_type = typename internal::meta_data_node::size_type;
843
845 meta_data() noexcept = default;
846
852 meta_data(const meta_ctx &area, internal::meta_data_node curr) noexcept
853 : node{std::move(curr)},
854 ctx{&area} {}
855
860 [[nodiscard]] size_type arity() const noexcept {
861 return node.arity;
862 }
863
868 [[nodiscard]] bool is_const() const noexcept {
869 return static_cast<bool>(node.traits & internal::meta_traits::is_const);
870 }
871
876 [[nodiscard]] bool is_static() const noexcept {
877 return static_cast<bool>(node.traits & internal::meta_traits::is_static);
878 }
879
881 [[nodiscard]] inline meta_type type() const noexcept;
882
890 template<typename Type>
891 // NOLINTNEXTLINE(modernize-use-nodiscard)
892 bool set(meta_handle instance, Type &&value) const {
893 return (node.set != nullptr) && node.set(meta_handle{*ctx, std::move(instance)}, meta_any{*ctx, std::forward<Type>(value)});
894 }
895
901 [[nodiscard]] meta_any get(meta_handle instance) const {
902 return (node.get != nullptr) ? node.get(meta_handle{*ctx, std::move(instance)}) : meta_any{meta_ctx_arg, *ctx};
903 }
904
910 [[nodiscard]] inline meta_type arg(size_type index) const noexcept;
911
917 template<typename Type>
918 [[nodiscard]] Type traits() const noexcept {
919 return internal::meta_to_user_traits<Type>(node.traits);
920 }
921
926 [[nodiscard]] meta_custom custom() const noexcept {
927 return {node.custom};
928 }
929
934 [[nodiscard]] explicit operator bool() const noexcept {
935 return (node.get != nullptr);
936 }
937
943 [[nodiscard]] bool operator==(const meta_data &other) const noexcept {
944 return (ctx == other.ctx) && (node.set == other.node.set) && (node.get == other.node.get);
945 }
946
947private:
948 internal::meta_data_node node{};
949 const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
950};
951
958[[nodiscard]] inline bool operator!=(const meta_data &lhs, const meta_data &rhs) noexcept {
959 return !(lhs == rhs);
960}
961
963struct meta_func {
965 using size_type = typename internal::meta_func_node::size_type;
966
968 meta_func() noexcept = default;
969
975 meta_func(const meta_ctx &area, internal::meta_func_node curr) noexcept
976 : node{std::move(curr)},
977 ctx{&area} {}
978
983 [[nodiscard]] size_type arity() const noexcept {
984 return node.arity;
985 }
986
991 [[nodiscard]] bool is_const() const noexcept {
992 return static_cast<bool>(node.traits & internal::meta_traits::is_const);
993 }
994
999 [[nodiscard]] bool is_static() const noexcept {
1000 return static_cast<bool>(node.traits & internal::meta_traits::is_static);
1001 }
1002
1007 [[nodiscard]] inline meta_type ret() const noexcept;
1008
1014 [[nodiscard]] inline meta_type arg(size_type index) const noexcept;
1015
1023 meta_any invoke(meta_handle instance, meta_any *const args, const size_type sz) const {
1024 return ((node.invoke != nullptr) && (sz == arity())) ? node.invoke(meta_handle{*ctx, std::move(instance)}, args) : meta_any{meta_ctx_arg, *ctx};
1025 }
1026
1034 template<typename... Args>
1035 // NOLINTNEXTLINE(modernize-use-nodiscard)
1036 meta_any invoke(meta_handle instance, Args &&...args) const {
1037 return invoke(std::move(instance), std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
1038 }
1039
1041 template<typename Type>
1042 [[nodiscard]] Type traits() const noexcept {
1043 return internal::meta_to_user_traits<Type>(node.traits);
1044 }
1045
1047 [[nodiscard]] meta_custom custom() const noexcept {
1048 return {node.custom};
1049 }
1050
1055 [[nodiscard]] meta_func next() const {
1056 return (node.next != nullptr) ? meta_func{*ctx, *node.next} : meta_func{};
1057 }
1058
1063 [[nodiscard]] explicit operator bool() const noexcept {
1064 return (node.invoke != nullptr);
1065 }
1066
1068 [[nodiscard]] bool operator==(const meta_func &other) const noexcept {
1069 return (ctx == other.ctx) && (node.invoke == other.node.invoke);
1070 }
1071
1072private:
1073 internal::meta_func_node node{};
1074 const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
1075};
1076
1083[[nodiscard]] inline bool operator!=(const meta_func &lhs, const meta_func &rhs) noexcept {
1084 return !(lhs == rhs);
1085}
1086
1089 template<typename Func>
1090 [[nodiscard]] auto lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, [[maybe_unused]] bool constness, Func next) const {
1091 decltype(next()) candidate = nullptr;
1092 size_type same{};
1093 bool ambiguous{};
1094
1095 for(auto curr = next(); curr; curr = next()) {
1096 if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) {
1097 if(constness && !static_cast<bool>(curr->traits & internal::meta_traits::is_const)) {
1098 continue;
1099 }
1100 }
1101
1102 if(curr->arity == sz) {
1103 size_type match{};
1104 size_type pos{};
1105
1106 // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span)
1107 for(; pos < sz && args[pos]; ++pos) {
1108 const auto other = curr->arg(*ctx, pos);
1109 const auto type = args[pos].type();
1110
1111 if(const auto &info = other.info(); info == type.info()) {
1112 ++match;
1113 } else if(!(type.node.conversion_helper && other.node.conversion_helper) && !(type.node.details && (internal::find_member<&internal::meta_base_node::type>(type.node.details->base, info.hash()) || internal::find_member<&internal::meta_conv_node::type>(type.node.details->conv, info.hash())))) {
1114 break;
1115 }
1116 }
1117 // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1118
1119 if(pos == sz) {
1120 if(!candidate || match > same) {
1121 candidate = curr;
1122 same = match;
1123 ambiguous = false;
1124 } else if(match == same) {
1125 if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) {
1126 if(static_cast<bool>(curr->traits & internal::meta_traits::is_const) != static_cast<bool>(candidate->traits & internal::meta_traits::is_const)) {
1127 candidate = static_cast<bool>(candidate->traits & internal::meta_traits::is_const) ? curr : candidate;
1128 ambiguous = false;
1129 continue;
1130 }
1131 }
1132
1133 ambiguous = true;
1134 }
1135 }
1136 }
1137 }
1138
1139 return ambiguous ? nullptr : candidate;
1140 }
1141
1142public:
1144 using size_type = typename internal::meta_type_node::size_type;
1145
1147 meta_type() noexcept = default;
1148
1154 meta_type(const meta_ctx &area, internal::meta_type_node curr) noexcept
1155 : node{std::move(curr)},
1156 ctx{&area} {}
1157
1163 meta_type(const meta_ctx &area, const internal::meta_base_node &curr) noexcept
1164 : meta_type{area, curr.resolve(internal::meta_context::from(area))} {}
1165
1170 [[nodiscard]] const type_info &info() const noexcept {
1171 return (node.info != nullptr) ? *node.info : type_id<void>();
1172 }
1173
1178 [[nodiscard]] id_type id() const noexcept {
1179 return node.id;
1180 }
1181
1186 [[nodiscard]] size_type size_of() const noexcept {
1187 return node.size_of;
1188 }
1189
1195 [[nodiscard]] bool is_arithmetic() const noexcept {
1196 return static_cast<bool>(node.traits & internal::meta_traits::is_arithmetic);
1197 }
1198
1203 [[nodiscard]] bool is_integral() const noexcept {
1204 return static_cast<bool>(node.traits & internal::meta_traits::is_integral);
1205 }
1206
1211 [[nodiscard]] bool is_signed() const noexcept {
1212 return static_cast<bool>(node.traits & internal::meta_traits::is_signed);
1213 }
1214
1219 [[nodiscard]] bool is_array() const noexcept {
1220 return static_cast<bool>(node.traits & internal::meta_traits::is_array);
1221 }
1222
1227 [[nodiscard]] bool is_enum() const noexcept {
1228 return static_cast<bool>(node.traits & internal::meta_traits::is_enum);
1229 }
1230
1235 [[nodiscard]] bool is_class() const noexcept {
1236 return static_cast<bool>(node.traits & internal::meta_traits::is_class);
1237 }
1238
1243 [[nodiscard]] bool is_pointer() const noexcept {
1244 return static_cast<bool>(node.traits & internal::meta_traits::is_pointer);
1245 }
1246
1252 [[nodiscard]] meta_type remove_pointer() const noexcept {
1253 return (node.remove_pointer != nullptr) ? meta_type{*ctx, node.remove_pointer(internal::meta_context::from(*ctx))} : *this;
1254 }
1255
1260 [[nodiscard]] bool is_pointer_like() const noexcept {
1261 return static_cast<bool>(node.traits & internal::meta_traits::is_pointer_like);
1262 }
1263
1268 [[nodiscard]] bool is_sequence_container() const noexcept {
1269 return static_cast<bool>(node.traits & internal::meta_traits::is_sequence_container);
1270 }
1271
1276 [[nodiscard]] bool is_associative_container() const noexcept {
1277 return static_cast<bool>(node.traits & internal::meta_traits::is_associative_container);
1278 }
1279
1286 [[nodiscard]] bool is_template_specialization() const noexcept {
1287 return (node.templ.arity != 0u);
1288 }
1289
1294 [[nodiscard]] size_type template_arity() const noexcept {
1295 return node.templ.arity;
1296 }
1297
1302 [[nodiscard]] meta_type template_type() const noexcept {
1303 return (node.templ.resolve != nullptr) ? meta_type{*ctx, node.templ.resolve(internal::meta_context::from(*ctx))} : meta_type{};
1304 }
1305
1311 [[nodiscard]] meta_type template_arg(const size_type index) const noexcept {
1312 return index < template_arity() ? meta_type{*ctx, node.templ.arg(internal::meta_context::from(*ctx), index)} : meta_type{};
1313 }
1314
1320 [[nodiscard]] bool can_cast(const meta_type &other) const noexcept {
1321 // casting this is UB in all cases but we aren't going to use the resulting pointer, so...
1322 return other && (internal::try_cast(internal::meta_context::from(*ctx), node, *other.node.info, this) != nullptr);
1323 }
1324
1330 [[nodiscard]] bool can_convert(const meta_type &other) const noexcept {
1331 return (internal::try_convert(internal::meta_context::from(*ctx), node, other.info(), other.is_arithmetic() || other.is_enum(), nullptr, [](const void *, auto &&...args) { return ((static_cast<void>(args), 1) + ... + 0u); }) != 0u);
1332 }
1333
1338 [[nodiscard]] meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator> base() const noexcept {
1339 using range_type = meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator>;
1340 return node.details ? range_type{{*ctx, node.details->base.cbegin()}, {*ctx, node.details->base.cend()}} : range_type{};
1341 }
1342
1347 [[nodiscard]] meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator> data() const noexcept {
1348 using range_type = meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator>;
1349 return node.details ? range_type{{*ctx, node.details->data.cbegin()}, {*ctx, node.details->data.cend()}} : range_type{};
1350 }
1351
1357 [[nodiscard]] meta_data data(const id_type id) const {
1358 const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), node, id);
1359 return (elem != nullptr) ? meta_data{*ctx, *elem} : meta_data{};
1360 }
1361
1366 [[nodiscard]] meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator> func() const noexcept {
1367 using return_type = meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator>;
1368 return node.details ? return_type{{*ctx, node.details->func.cbegin()}, {*ctx, node.details->func.cend()}} : return_type{};
1369 }
1370
1376 [[nodiscard]] meta_func func(const id_type id) const {
1377 const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node, id);
1378 return (elem != nullptr) ? meta_func{*ctx, *elem} : meta_func{};
1379 }
1380
1387 [[nodiscard]] meta_any construct(meta_any *const args, const size_type sz) const {
1388 if(node.details) {
1389 if(const auto *candidate = lookup(args, sz, false, [first = node.details->ctor.cbegin(), last = node.details->ctor.cend()]() mutable { return first == last ? nullptr : &*(first++); }); candidate) {
1390 return candidate->invoke(*ctx, args);
1391 }
1392 }
1393
1394 if(sz == 0u && (node.default_constructor != nullptr)) {
1395 return node.default_constructor(*ctx);
1396 }
1397
1398 return meta_any{meta_ctx_arg, *ctx};
1399 }
1400
1407 template<typename... Args>
1408 [[nodiscard]] meta_any construct(Args &&...args) const {
1409 return construct(std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
1410 // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
1411 }
1412
1419 [[nodiscard]] meta_any from_void(void *elem, bool transfer_ownership = false) const {
1420 return ((elem != nullptr) && (node.from_void != nullptr)) ? node.from_void(*ctx, elem, transfer_ownership ? elem : nullptr) : meta_any{meta_ctx_arg, *ctx};
1421 }
1422
1428 [[nodiscard]] meta_any from_void(const void *elem) const {
1429 return ((elem != nullptr) && (node.from_void != nullptr)) ? node.from_void(*ctx, nullptr, elem) : meta_any{meta_ctx_arg, *ctx};
1430 }
1431
1440 // NOLINTNEXTLINE(modernize-use-nodiscard)
1441 meta_any invoke(const id_type id, meta_handle instance, meta_any *const args, const size_type sz) const {
1442 if(node.details) {
1443 if(auto *elem = internal::find_member<&internal::meta_func_node::id>(node.details->func, id); elem != nullptr) {
1444 if(const auto *candidate = lookup(args, sz, (instance->base().policy() == any_policy::cref), [curr = elem]() mutable { return (curr != nullptr) ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) {
1445 return candidate->invoke(meta_handle{*ctx, std::move(instance)}, args);
1446 }
1447 }
1448 }
1449
1450 for(auto &&curr: base()) {
1451 if(auto elem = curr.second.invoke(id, *instance.operator->(), args, sz); elem) {
1452 return elem;
1453 }
1454 }
1455
1456 return meta_any{meta_ctx_arg, *ctx};
1457 }
1458
1467 template<typename... Args>
1468 // NOLINTNEXTLINE(modernize-use-nodiscard)
1469 meta_any invoke(const id_type id, meta_handle instance, Args &&...args) const {
1470 return invoke(id, std::move(instance), std::array<meta_any, sizeof...(Args)>{meta_any{*ctx, std::forward<Args>(args)}...}.data(), sizeof...(Args));
1471 }
1472
1481 template<typename Type>
1482 // NOLINTNEXTLINE(modernize-use-nodiscard)
1483 bool set(const id_type id, meta_handle instance, Type &&value) const {
1484 const auto candidate = data(id);
1485 return candidate && candidate.set(std::move(instance), std::forward<Type>(value));
1486 }
1487
1494 [[nodiscard]] meta_any get(const id_type id, meta_handle instance) const {
1495 const auto candidate = data(id);
1496 return candidate ? candidate.get(std::move(instance)) : meta_any{meta_ctx_arg, *ctx};
1497 }
1498
1500 template<typename Type>
1501 [[nodiscard]] Type traits() const noexcept {
1502 return internal::meta_to_user_traits<Type>(node.traits);
1503 }
1504
1506 [[nodiscard]] meta_custom custom() const noexcept {
1507 return {node.custom};
1508 }
1509
1514 [[nodiscard]] explicit operator bool() const noexcept {
1515 return (node.info != nullptr);
1516 }
1517
1519 [[nodiscard]] bool operator==(const meta_type &other) const noexcept {
1520 // NOLINTNEXTLINE(clang-analyzer-core.NonNullParamChecker)
1521 return (ctx == other.ctx) && ((node.info == nullptr) == (other.node.info == nullptr)) && (node.info == nullptr || (*node.info == *other.node.info));
1522 }
1523
1524private:
1525 internal::meta_type_node node{};
1526 const meta_ctx *ctx{&locator<meta_ctx>::value_or()};
1527};
1528
1535[[nodiscard]] inline bool operator!=(const meta_type &lhs, const meta_type &rhs) noexcept {
1536 return !(lhs == rhs);
1537}
1538
1539[[nodiscard]] inline meta_type meta_any::type() const noexcept {
1540 return (node.info != nullptr) ? meta_type{*ctx, node} : meta_type{};
1541}
1542
1543template<typename... Args>
1544// NOLINTNEXTLINE(modernize-use-nodiscard)
1545meta_any meta_any::invoke(const id_type id, Args &&...args) const {
1546 return type().invoke(id, *this, std::forward<Args>(args)...);
1547}
1548
1549template<typename... Args>
1550meta_any meta_any::invoke(const id_type id, Args &&...args) {
1551 return type().invoke(id, *this, std::forward<Args>(args)...);
1552}
1553
1554template<typename Type>
1555bool meta_any::set(const id_type id, Type &&value) {
1556 return type().set(id, *this, std::forward<Type>(value));
1557}
1558
1559[[nodiscard]] inline meta_any meta_any::get(const id_type id) const {
1560 return type().get(id, *this);
1561}
1562
1563[[nodiscard]] inline meta_any meta_any::get(const id_type id) {
1564 return type().get(id, *this);
1565}
1566
1567[[nodiscard]] inline meta_any meta_any::allow_cast(const meta_type &type) const {
1568 return internal::try_convert(internal::meta_context::from(*ctx), node, type.info(), type.is_arithmetic() || type.is_enum(), storage.data(), [this, &type]([[maybe_unused]] const void *instance, [[maybe_unused]] auto &&...args) {
1569 if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<decltype(args)>>, internal::meta_type_node> || ...)) {
1570 return (args.from_void(*ctx, nullptr, instance), ...);
1571 } else if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<decltype(args)>>, internal::meta_conv_node> || ...)) {
1572 return (args.conv(*ctx, instance), ...);
1573 } else if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<decltype(args)>>, decltype(internal::meta_type_node::conversion_helper)> || ...)) {
1574 // exploits the fact that arithmetic types and enums are also default constructible
1575 auto other = type.construct();
1576 const auto value = (args(nullptr, instance), ...);
1577 other.node.conversion_helper(other.storage.data(), &value);
1578 return other;
1579 } else {
1580 // forwards to force a compile-time error in case of available arguments
1581 return meta_any{meta_ctx_arg, *ctx, std::forward<decltype(args)>(args)...};
1582 }
1583 });
1584}
1585
1586inline bool meta_any::assign(const meta_any &other) {
1587 auto value = other.allow_cast({*ctx, node});
1588 return value && storage.assign(value.storage);
1589}
1590
1591inline bool meta_any::assign(meta_any &&other) {
1592 if(*node.info == *other.node.info) {
1593 return storage.assign(std::move(other.storage));
1594 }
1595
1596 return assign(std::as_const(other));
1597}
1598
1599[[nodiscard]] inline meta_type meta_data::type() const noexcept {
1600 return (node.type != nullptr) ? meta_type{*ctx, node.type(internal::meta_context::from(*ctx))} : meta_type{};
1601}
1602
1603[[nodiscard]] inline meta_type meta_data::arg(const size_type index) const noexcept {
1604 return index < arity() ? node.arg(*ctx, index) : meta_type{};
1605}
1606
1607[[nodiscard]] inline meta_type meta_func::ret() const noexcept {
1608 return (node.ret != nullptr) ? meta_type{*ctx, node.ret(internal::meta_context::from(*ctx))} : meta_type{};
1609}
1610
1611[[nodiscard]] inline meta_type meta_func::arg(const size_type index) const noexcept {
1612 return index < arity() ? node.arg(*ctx, index) : meta_type{};
1613}
1614
1616class meta_sequence_container::meta_iterator final {
1617 using vtable_type = void(const void *, const std::ptrdiff_t, meta_any *);
1618
1619 template<typename It>
1620 static void basic_vtable(const void *value, const std::ptrdiff_t offset, meta_any *other) {
1621 const auto &it = *static_cast<const It *>(value);
1622 other ? other->emplace<decltype(*it)>(*it) : std::advance(const_cast<It &>(it), offset);
1623 }
1624
1625public:
1626 using value_type = meta_any;
1627 using pointer = input_iterator_pointer<value_type>;
1628 using reference = value_type;
1629 using difference_type = std::ptrdiff_t;
1630 using iterator_category = std::input_iterator_tag;
1631 using iterator_concept = std::bidirectional_iterator_tag;
1632
1633 meta_iterator() = default;
1634
1635 template<typename It>
1636 meta_iterator(const meta_ctx &area, It iter) noexcept
1637 : ctx{&area},
1638 vtable{&basic_vtable<It>},
1639 handle{iter} {}
1640
1641 meta_iterator &operator++() noexcept {
1642 vtable(handle.data(), 1, nullptr);
1643 return *this;
1644 }
1645
1646 meta_iterator operator++(int value) noexcept {
1647 meta_iterator orig = *this;
1648 vtable(handle.data(), ++value, nullptr);
1649 return orig;
1650 }
1651
1652 meta_iterator &operator--() noexcept {
1653 vtable(handle.data(), -1, nullptr);
1654 return *this;
1655 }
1656
1657 meta_iterator operator--(int value) noexcept {
1658 meta_iterator orig = *this;
1659 vtable(handle.data(), --value, nullptr);
1660 return orig;
1661 }
1662
1663 [[nodiscard]] reference operator*() const {
1664 reference other{meta_ctx_arg, *ctx};
1665 vtable(handle.data(), 0, &other);
1666 return other;
1667 }
1668
1669 [[nodiscard]] pointer operator->() const {
1670 return operator*();
1671 }
1672
1673 [[nodiscard]] explicit operator bool() const noexcept {
1674 return (vtable != nullptr);
1675 }
1676
1677 [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
1678 return handle == other.handle;
1679 }
1680
1681 [[nodiscard]] bool operator!=(const meta_iterator &other) const noexcept {
1682 return !(*this == other);
1683 }
1684
1685 [[nodiscard]] const any &base() const noexcept {
1686 return handle;
1687 }
1688
1689private:
1690 const meta_ctx *ctx{};
1691 vtable_type *vtable{};
1692 any handle;
1693};
1694
1695class meta_associative_container::meta_iterator final {
1696 using vtable_type = void(const void *, std::pair<meta_any, meta_any> *);
1697
1698 template<bool KeyOnly, typename It>
1699 static void basic_vtable(const void *value, std::pair<meta_any, meta_any> *other) {
1700 if(const auto &it = *static_cast<const It *>(value); other) {
1701 if constexpr(KeyOnly) {
1702 other->first.emplace<decltype(*it)>(*it);
1703 } else {
1704 other->first.emplace<decltype((it->first))>(it->first);
1705 other->second.emplace<decltype((it->second))>(it->second);
1706 }
1707 } else {
1708 ++const_cast<It &>(it);
1709 }
1710 }
1711
1712public:
1713 using value_type = std::pair<meta_any, meta_any>;
1714 using pointer = input_iterator_pointer<value_type>;
1715 using reference = value_type;
1716 using difference_type = std::ptrdiff_t;
1717 using iterator_category = std::input_iterator_tag;
1718 using iterator_concept = std::forward_iterator_tag;
1719
1720 meta_iterator() = default;
1721
1722 template<bool KeyOnly, typename It>
1723 meta_iterator(const meta_ctx &area, std::bool_constant<KeyOnly>, It iter) noexcept
1724 : ctx{&area},
1725 vtable{&basic_vtable<KeyOnly, It>},
1726 handle{iter} {}
1727
1728 meta_iterator &operator++() noexcept {
1729 vtable(handle.data(), nullptr);
1730 return *this;
1731 }
1732
1733 meta_iterator operator++(int) noexcept {
1734 meta_iterator orig = *this;
1735 vtable(handle.data(), nullptr);
1736 return orig;
1737 }
1738
1739 [[nodiscard]] reference operator*() const {
1740 reference other{{meta_ctx_arg, *ctx}, {meta_ctx_arg, *ctx}};
1741 vtable(handle.data(), &other);
1742 return other;
1743 }
1744
1745 [[nodiscard]] pointer operator->() const {
1746 return operator*();
1747 }
1748
1749 [[nodiscard]] explicit operator bool() const noexcept {
1750 return (vtable != nullptr);
1751 }
1752
1753 [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
1754 return handle == other.handle;
1755 }
1756
1757 [[nodiscard]] bool operator!=(const meta_iterator &other) const noexcept {
1758 return !(*this == other);
1759 }
1760
1761private:
1762 const meta_ctx *ctx{};
1763 vtable_type *vtable{};
1764 any handle;
1765};
1767
1772[[nodiscard]] inline meta_type meta_sequence_container::value_type() const noexcept {
1773 return (value_type_node != nullptr) ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1774}
1775
1781 return size_fn(data);
1782}
1783
1790 return !const_only && resize_fn(const_cast<void *>(data), sz);
1791}
1792
1798 return !const_only && clear_fn(const_cast<void *>(data));
1799}
1800
1807 return !const_only && reserve_fn(const_cast<void *>(data), sz);
1808}
1809
1815 return begin_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data);
1816}
1817
1823 return end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data);
1824}
1825
1833 // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
1834 if(const auto vtype = value_type_node(internal::meta_context::from(*ctx)); !const_only && (value.allow_cast({*ctx, vtype}) || value.allow_cast({*ctx, const_reference_node(internal::meta_context::from(*ctx))}))) {
1835 const bool is_value_type = (value.type().info() == *vtype.info);
1836 return insert_fn(*ctx, const_cast<void *>(data), is_value_type ? value.base().data() : nullptr, is_value_type ? nullptr : value.base().data(), it);
1837 }
1838
1839 return iterator{};
1840}
1841
1848 return const_only ? iterator{} : erase_fn(*ctx, const_cast<void *>(data), it);
1849}
1850
1857 auto it = begin();
1858 it.operator++(static_cast<int>(pos) - 1);
1859 return *it;
1860}
1861
1866[[nodiscard]] inline meta_sequence_container::operator bool() const noexcept {
1867 return (data != nullptr);
1868}
1869
1874[[nodiscard]] inline meta_type meta_associative_container::key_type() const noexcept {
1875 return (key_type_node != nullptr) ? meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1876}
1877
1882[[nodiscard]] inline meta_type meta_associative_container::mapped_type() const noexcept {
1883 return (mapped_type_node != nullptr) ? meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1884}
1885
1887[[nodiscard]] inline meta_type meta_associative_container::value_type() const noexcept {
1888 return (value_type_node != nullptr) ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
1889}
1890
1893 return size_fn(data);
1894}
1895
1898 return !const_only && clear_fn(const_cast<void *>(data));
1899}
1900
1903 return !const_only && reserve_fn(const_cast<void *>(data), sz);
1904}
1905
1908 return begin_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data);
1909}
1910
1913 return end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data);
1914}
1915
1923 return !const_only && key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})
1924 && ((mapped_type_node == nullptr) || value.allow_cast(meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))}))
1925 && insert_fn(const_cast<void *>(data), key.base().data(), value.base().data());
1926}
1927
1934 return (!const_only && key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})) ? erase_fn(const_cast<void *>(data), key.base().data()) : 0u;
1935}
1936
1943 return key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))}) ? find_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, key.base().data()) : iterator{};
1944}
1945
1950[[nodiscard]] inline meta_associative_container::operator bool() const noexcept {
1951 return (data != nullptr);
1952}
1953
1954} // namespace entt
1955
1956#endif
const void * data() const noexcept
Returns an opaque pointer to the contained instance.
Definition any.hpp:305
any_policy policy() const noexcept
Returns the current mode of an any object.
Definition any.hpp:441
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:166
bool assign(const meta_any &other)
Assigns a value to the contained object without replacing it.
Definition meta.hpp:1586
any_policy policy() const noexcept
Returns the current mode of a meta any object.
Definition meta.hpp:637
meta_any & operator=(const meta_any &other)
Copy assignment operator.
Definition meta.hpp:348
meta_associative_container as_associative_container() noexcept
Returns an associative container proxy.
Definition meta.hpp:581
meta_type type() const noexcept
Returns the object type if any, type_id<void>() otherwise.
Definition meta.hpp:1539
meta_any(const meta_ctx &area, const meta_any &other)
Context aware copy constructor.
Definition meta.hpp:305
meta_any()=default
meta_any invoke(id_type id, Args &&...args) const
Invokes the underlying function, if possible.
Definition meta.hpp:1545
std::remove_const_t< Type > cast()
Tries to cast an instance to a given type.
Definition meta.hpp:474
meta_any(meta_any &&other) noexcept
Move constructor.
Definition meta.hpp:332
void * data() noexcept
Returns an opaque pointer to the contained instance.
Definition meta.hpp:399
meta_any(std::in_place_type_t< Type >, Args &&...args)
Constructs a wrapper by directly initializing the new object.
Definition meta.hpp:239
std::remove_const_t< Type > cast() const
Tries to cast an instance to a given type.
Definition meta.hpp:466
meta_any as_ref() noexcept
Aliasing constructor.
Definition meta.hpp:624
const Type * try_cast() const
Tries to cast an instance to a given type.
Definition meta.hpp:443
void emplace(Args &&...args)
Replaces the contained object by creating a new instance directly.
Definition meta.hpp:539
meta_any(std::in_place_t, Type *value)
Constructs a wrapper taking ownership of the passed object.
Definition meta.hpp:262
meta_any(const meta_ctx &area, meta_any &&other)
Context aware move constructor.
Definition meta.hpp:316
meta_sequence_container as_sequence_container() noexcept
Returns a sequence container proxy.
Definition meta.hpp:564
Type * try_cast()
Tries to cast an instance to a given type.
Definition meta.hpp:450
meta_associative_container as_associative_container() const noexcept
Returns an associative container proxy.
Definition meta.hpp:588
meta_any(const meta_any &other)=default
Copy constructor.
meta_any operator*() const noexcept
Indirection operator for dereferencing opaque objects.
Definition meta.hpp:599
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:1567
meta_any(const meta_ctx &area, Type &&value)
Constructs a wrapper from a given value.
Definition meta.hpp:297
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:250
const any & base() const noexcept
Returns the underlying storage.
Definition meta.hpp:645
meta_any as_ref() const noexcept
Aliasing constructor.
Definition meta.hpp:629
meta_any allow_cast() const
Converts an object in such a way that a given cast becomes viable.
Definition meta.hpp:513
meta_any(meta_ctx_arg_t, const meta_ctx &area)
Context aware constructor.
Definition meta.hpp:229
meta_any(Type &&value)
Constructs a wrapper from a given value.
Definition meta.hpp:287
~meta_any()
Frees the internal storage, whatever it means.
Definition meta.hpp:339
void reset()
Destroys contained object.
Definition meta.hpp:553
meta_any & operator=(Type &&value)
Value assignment operator.
Definition meta.hpp:385
meta_any(const meta_ctx &area, std::in_place_t, Type *value)
Constructs a wrapper taking ownership of the passed object.
Definition meta.hpp:272
meta_sequence_container as_sequence_container() const noexcept
Returns a sequence container proxy.
Definition meta.hpp:571
bool operator==(const meta_any &other) const noexcept
Checks if two wrappers differ in their content.
Definition meta.hpp:614
const void * data() const noexcept
Returns an opaque pointer to the contained instance.
Definition meta.hpp:394
bool operator!=(const meta_any &other) const noexcept
Checks if two wrappers differ in their content.
Definition meta.hpp:619
bool set(id_type id, Type &&value)
Sets the value of a given variable.
Definition meta.hpp:1555
bool allow_cast()
Converts an object in such a way that a given cast becomes viable.
Definition meta.hpp:528
meta_any get(id_type id) const
Gets the value of a given variable.
Definition meta.hpp:1559
bool allow_cast(const meta_type &type)
Converts an object in such a way that a given cast becomes viable.
Definition meta.hpp:494
meta_any & operator=(meta_any &&other) noexcept
Move assignment operator.
Definition meta.hpp:369
const meta_ctx & context() const noexcept
Returns the underlying meta context.
Definition meta.hpp:653
Proxy object for associative containers.
Definition meta.hpp:94
meta_associative_container()=default
Default constructor.
size_type erase(meta_any)
Removes the specified element from a container.
Definition meta.hpp:1933
iterator find(meta_any)
Returns an iterator to the element with a given key, if any.
Definition meta.hpp:1942
bool insert(meta_any, meta_any)
Inserts a key-only or key/value element into a container.
Definition meta.hpp:1922
iterator end()
Returns an iterator that is past the last element of a container.
Definition meta.hpp:1912
bool reserve(size_type)
Reserves storage for at least the given number of elements.
Definition meta.hpp:1902
meta_associative_container(const meta_ctx &area, Type &instance) noexcept
Context aware constructor.
Definition meta.hpp:113
iterator begin()
Returns an iterator to the first element of a container.
Definition meta.hpp:1907
size_type size() const noexcept
Returns the size of a container.
Definition meta.hpp:1892
meta_type mapped_type() const noexcept
Returns the meta mapped type of a container.
Definition meta.hpp:1882
std::size_t size_type
Unsigned integer type.
Definition meta.hpp:99
meta_iterator iterator
Meta iterator type.
Definition meta.hpp:101
meta_type value_type() const noexcept
Returns the meta value type of a container.
Definition meta.hpp:1887
meta_type key_type() const noexcept
Returns the meta key type of a container.
Definition meta.hpp:1874
bool clear()
Clears the content of a container.
Definition meta.hpp:1897
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:31
bool reserve(size_type)
Reserves storage for at least the given number of elements.
Definition meta.hpp:1806
iterator insert(const iterator &, meta_any)
Inserts an element at a specified location of a container.
Definition meta.hpp:1832
meta_type value_type() const noexcept
Returns the meta value type of a container.
Definition meta.hpp:1772
meta_any operator[](size_type)
Returns a reference to the element at a given location of a container.
Definition meta.hpp:1856
meta_sequence_container()=default
Default constructor.
iterator end()
Returns an iterator that is past the last element of a container.
Definition meta.hpp:1822
iterator erase(const iterator &)
Removes a given element from a container.
Definition meta.hpp:1847
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:1789
size_type size() const noexcept
Returns the size of a container.
Definition meta.hpp:1780
iterator begin()
Returns an iterator to the first element of a container.
Definition meta.hpp:1814
bool clear()
Clears the content of a container.
Definition meta.hpp:1797
Opaque wrapper for types.
Definition meta.hpp:1088
bool is_pointer() const noexcept
Checks whether a type refers to a pointer or not.
Definition meta.hpp:1243
bool is_arithmetic() const noexcept
Checks whether a type refers to an arithmetic type or not.
Definition meta.hpp:1195
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:1366
meta_custom custom() const noexcept
Returns user defined data for a given meta object.
Definition meta.hpp:1506
meta_any from_void(void *elem, bool transfer_ownership=false) const
Wraps an opaque element of the underlying type.
Definition meta.hpp:1419
id_type id() const noexcept
Returns the identifier assigned to a type.
Definition meta.hpp:1178
meta_func func(const id_type id) const
Lookup utility for meta functions (bases are also visited).
Definition meta.hpp:1376
meta_type remove_pointer() const noexcept
Provides the type for which the pointer is defined.
Definition meta.hpp:1252
meta_any construct(Args &&...args) const
Creates an instance of the underlying type, if possible.
Definition meta.hpp:1408
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:1311
bool is_array() const noexcept
Checks whether a type refers to an array type or not.
Definition meta.hpp:1219
meta_data data(const id_type id) const
Lookup utility for meta data (bases are also visited).
Definition meta.hpp:1357
bool is_class() const noexcept
Checks whether a type refers to a class or not.
Definition meta.hpp:1235
bool set(const id_type id, meta_handle instance, Type &&value) const
Sets the value of a given variable.
Definition meta.hpp:1483
typename internal::meta_type_node::size_type size_type
Unsigned integer type.
Definition meta.hpp:1144
meta_any from_void(const void *elem) const
Wraps an opaque element of the underlying type.
Definition meta.hpp:1428
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:1347
meta_any invoke(const id_type id, meta_handle instance, Args &&...args) const
Invokes a function given an identifier, if possible.
Definition meta.hpp:1469
bool can_convert(const meta_type &other) const noexcept
Checks if a type supports conversion it to another type.
Definition meta.hpp:1330
bool is_signed() const noexcept
Checks whether a type refers to a signed type or not.
Definition meta.hpp:1211
bool is_enum() const noexcept
Checks whether a type refers to an enum or not.
Definition meta.hpp:1227
bool can_cast(const meta_type &other) const noexcept
Checks if a type supports direct casting to another type.
Definition meta.hpp:1320
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:1519
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:1338
bool is_pointer_like() const noexcept
Checks whether a type is a pointer-like type or not.
Definition meta.hpp:1260
meta_any get(const id_type id, meta_handle instance) const
Gets the value of a given variable.
Definition meta.hpp:1494
Type traits() const noexcept
Returns all meta traits for a given meta object.
Definition meta.hpp:1501
meta_any construct(meta_any *const args, const size_type sz) const
Creates an instance of the underlying type, if possible.
Definition meta.hpp:1387
bool is_integral() const noexcept
Checks whether a type refers to an integral type or not.
Definition meta.hpp:1203
meta_type template_type() const noexcept
Returns a tag for the class template of the underlying type.
Definition meta.hpp:1302
meta_type(const meta_ctx &area, const internal::meta_base_node &curr) noexcept
Context aware constructor for meta objects.
Definition meta.hpp:1163
const type_info & info() const noexcept
Returns the type info object of the underlying type.
Definition meta.hpp:1170
bool is_template_specialization() const noexcept
Checks whether a type refers to a recognized class template specialization or not.
Definition meta.hpp:1286
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:1441
bool is_associative_container() const noexcept
Checks whether a type refers to an associative container or not.
Definition meta.hpp:1276
size_type template_arity() const noexcept
Returns the number of template arguments.
Definition meta.hpp:1294
size_type size_of() const noexcept
Returns the size of the underlying type if known.
Definition meta.hpp:1186
bool is_sequence_container() const noexcept
Checks whether a type refers to a sequence container or not.
Definition meta.hpp:1268
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::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:672
meta_type resolve(const meta_ctx &ctx) noexcept
Returns the meta type associated with a given type.
Definition resolve.hpp:21
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
const type_info & type_id() noexcept
Returns the type info object associated to a given type.
any_policy
Possible modes of an any object.
Definition fwd.hpp:11
@ ref
Aliasing mode, the object points to a non-const element.
Definition fwd.hpp:19
@ cref
Const aliasing mode, the object points to a const element.
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:805
meta_custom() noexcept=default
Default constructor.
Opaque wrapper for data members.
Definition meta.hpp:840
bool is_const() const noexcept
Indicates whether a data member is constant or not.
Definition meta.hpp:868
meta_type arg(size_type index) const noexcept
Returns the type accepted by the i-th setter.
Definition meta.hpp:1603
typename internal::meta_data_node::size_type size_type
Unsigned integer type.
Definition meta.hpp:842
meta_any get(meta_handle instance) const
Gets the value of a given variable.
Definition meta.hpp:901
size_type arity() const noexcept
Returns the number of setters available.
Definition meta.hpp:860
bool operator==(const meta_data &other) const noexcept
Checks if two objects refer to the same type.
Definition meta.hpp:943
bool set(meta_handle instance, Type &&value) const
Sets the value of a given variable.
Definition meta.hpp:892
meta_custom custom() const noexcept
Returns user defined data for a given meta object.
Definition meta.hpp:926
meta_type type() const noexcept
Returns the object type if any, type_id<void>() otherwise.
Definition meta.hpp:1599
meta_data() noexcept=default
Default constructor.
bool is_static() const noexcept
Indicates whether a data member is static or not.
Definition meta.hpp:876
Type traits() const noexcept
Returns all meta traits for a given meta object.
Definition meta.hpp:918
Opaque wrapper for member functions.
Definition meta.hpp:963
bool is_static() const noexcept
Indicates whether a member function is static or not.
Definition meta.hpp:999
typename internal::meta_func_node::size_type size_type
Unsigned integer type.
Definition meta.hpp:965
meta_func() noexcept=default
Default constructor.
meta_type ret() const noexcept
Returns the return type of a member function.
Definition meta.hpp:1607
bool operator==(const meta_func &other) const noexcept
Checks if two objects refer to the same type.
Definition meta.hpp:1068
Type traits() const noexcept
Returns all meta traits for a given meta object.
Definition meta.hpp:1042
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:991
meta_any invoke(meta_handle instance, Args &&...args) const
Invokes the underlying function, if possible.
Definition meta.hpp:1036
meta_custom custom() const noexcept
Returns user defined data for a given meta object.
Definition meta.hpp:1047
meta_func next() const
Returns the next overload of a given function, if any.
Definition meta.hpp:1055
meta_type arg(size_type index) const noexcept
Returns the type of the i-th argument of a member function.
Definition meta.hpp:1611
size_type arity() const noexcept
Returns the number of arguments accepted by a member function.
Definition meta.hpp:983
Opaque pointers to instances of any type.
Definition meta.hpp:688
bool operator!=(const meta_handle &other) const noexcept
Checks if two wrappers differ in their content.
Definition meta.hpp:783
meta_handle(const meta_any &value)
Creates a handle that points to an unmanaged object.
Definition meta.hpp:710
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:720
~meta_handle()=default
Default destructor.
meta_handle()=default
meta_handle(const meta_ctx &area, const meta_handle &other)
Context aware copy constructor.
Definition meta.hpp:737
bool operator==(const meta_handle &other) const noexcept
Checks if two wrappers differ in their content.
Definition meta.hpp:778
meta_handle(meta_handle &&)=default
Default move constructor.
meta_handle(const meta_ctx &area, meta_handle &&other)
Context aware move constructor.
Definition meta.hpp:745
const meta_any * operator->() const
Access operator for accessing the contained opaque object.
Definition meta.hpp:796
meta_handle(const meta_handle &)=delete
Default copy constructor, deleted on purpose.
meta_handle(meta_ctx_arg_t, const meta_ctx &area)
Context aware constructor.
Definition meta.hpp:696
meta_handle(meta_any &value)
Creates a handle that points to an unmanaged object.
Definition meta.hpp:703
meta_handle(Type &value)
Creates a handle that points to an unmanaged object.
Definition meta.hpp:729
meta_handle & operator=(meta_handle &&)=default
Default move assignment operator.
meta_any * operator->()
Access operator for accessing the contained opaque object.
Definition meta.hpp:791
Implementation specific information about a type.