1 #ifndef ENTT_META_META_HPP
2 #define ENTT_META_META_HPP
10 #include <type_traits>
12 #include "../config/config.h"
13 #include "../core/fwd.hpp"
14 #include "../core/utility.hpp"
16 #include "internal.hpp"
18 #include "type_traits.hpp"
31 struct meta_sequence_container_proxy;
51 template<
typename Type>
53 : value_type_fn{&meta_sequence_container_proxy<Type>::value_type},
54 size_fn{&meta_sequence_container_proxy<Type>::size},
55 resize_fn{&meta_sequence_container_proxy<Type>::resize},
56 clear_fn{&meta_sequence_container_proxy<Type>::clear},
57 begin_fn{&meta_sequence_container_proxy<Type>::begin},
58 end_fn{&meta_sequence_container_proxy<Type>::end},
59 insert_fn{&meta_sequence_container_proxy<Type>::insert},
60 erase_fn{&meta_sequence_container_proxy<Type>::erase},
61 get_fn{&meta_sequence_container_proxy<Type>::get},
65 [[nodiscard]]
inline meta_type
value_type() const ENTT_NOEXCEPT;
73 [[nodiscard]] inline meta_any operator[](
size_type);
74 [[nodiscard]] inline explicit operator
bool() const ENTT_NOEXCEPT;
77 meta_type(* value_type_fn)() ENTT_NOEXCEPT;
78 size_type(* size_fn)(const
void *) ENTT_NOEXCEPT;
80 bool(* clear_fn)(
void *);
93 struct meta_associative_container_proxy;
113 template<
typename Type>
115 : key_only_container{is_key_only_meta_associative_container_v<Type>},
116 key_type_fn{&meta_associative_container_proxy<Type>::key_type},
117 mapped_type_fn{&meta_associative_container_proxy<Type>::mapped_type},
118 value_type_fn{&meta_associative_container_proxy<Type>::value_type},
119 size_fn{&meta_associative_container_proxy<Type>::size},
120 clear_fn{&meta_associative_container_proxy<Type>::clear},
121 begin_fn{&meta_associative_container_proxy<Type>::begin},
122 end_fn{&meta_associative_container_proxy<Type>::end},
123 insert_fn{&meta_associative_container_proxy<Type>::insert},
124 erase_fn{&meta_associative_container_proxy<Type>::erase},
125 find_fn{&meta_associative_container_proxy<Type>::find},
129 [[nodiscard]]
inline bool key_only() const ENTT_NOEXCEPT;
130 [[nodiscard]] inline meta_type key_type() const ENTT_NOEXCEPT;
131 [[nodiscard]] inline meta_type mapped_type() const ENTT_NOEXCEPT;
132 [[nodiscard]] inline meta_type
value_type() const ENTT_NOEXCEPT;
137 inline
bool insert(meta_any, meta_any);
138 inline
bool erase(meta_any);
139 [[nodiscard]] inline
iterator find(meta_any);
140 [[nodiscard]] inline explicit operator
bool() const ENTT_NOEXCEPT;
143 bool key_only_container;
144 meta_type(* key_type_fn)() ENTT_NOEXCEPT;
145 meta_type(* mapped_type_fn)() ENTT_NOEXCEPT;
146 meta_type(* value_type_fn)() ENTT_NOEXCEPT;
147 size_type(* size_fn)(const
void *) ENTT_NOEXCEPT;
148 bool(* clear_fn)(
void *);
151 bool(* insert_fn)(
void *, meta_any, meta_any);
152 bool(* erase_fn)(
void *, meta_any);
153 iterator(* find_fn)(
void *, meta_any);
167 template<
typename Type>
169 if constexpr(is_meta_pointer_like_v<Type>) {
170 using pointed_type = std::remove_reference_t<decltype(*std::declval<Type>())>;
172 if constexpr(std::is_const_v<pointed_type> && std::is_copy_constructible_v<pointed_type>) {
173 return std::as_const(*any.
cast<Type>());
174 }
else if constexpr(!std::is_const_v<pointed_type>) {
175 return std::ref(*any.
cast<Type>());
184 template<
typename Type>
185 [[nodiscard]]
static meta_sequence_container meta_sequence_container_factory([[maybe_unused]]
void *container) ENTT_NOEXCEPT {
186 if constexpr(has_meta_sequence_container_traits_v<Type>) {
187 return static_cast<Type *
>(container);
193 template<
typename Type>
194 [[nodiscard]]
static meta_associative_container meta_associative_container_factory([[maybe_unused]]
void *container) ENTT_NOEXCEPT {
195 if constexpr(has_meta_associative_container_traits_v<Type>) {
196 return static_cast<Type *
>(container);
208 seq_factory{
nullptr},
209 assoc_factory{
nullptr}
218 template<
typename Type,
typename... Args>
219 explicit meta_any(std::in_place_type_t<Type>, [[maybe_unused]] Args &&... args)
220 :
storage(std::in_place_type<Type>, std::forward<Args>(args)...),
221 node{internal::meta_info<Type>::resolve()},
222 deref{&dereference_operator<Type>},
223 seq_factory{&meta_sequence_container_factory<Type>},
224 assoc_factory{&meta_associative_container_factory<Type>}
232 template<
typename Type>
235 node{internal::meta_info<Type>::resolve()},
236 deref{&dereference_operator<Type>},
237 seq_factory{&meta_sequence_container_factory<Type>},
238 assoc_factory{&meta_associative_container_factory<Type>}
246 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_any>>>
248 :
meta_any{std::in_place_type<std::remove_cv_t<std::remove_reference_t<Type>>>, std::forward<Type>(value)}
269 if(node && node->dtor) {
288 [[nodiscard]]
inline meta_type type() const ENTT_NOEXCEPT;
294 [[nodiscard]] const
void * data() const ENTT_NOEXCEPT {
299 [[nodiscard]]
void *
data() ENTT_NOEXCEPT {
313 template<
typename... Args>
327 template<
typename Type>
328 bool set(
const id_type id, Type &&value)
const;
342 template<
typename Type>
345 if(
const auto type_id = internal::meta_info<Type>::resolve()->type_id; node->type_id == type_id) {
347 }
else if(
const auto *base = internal::find_if<&internal::meta_type_node::base>([type_id](
const auto *curr) {
return curr->type()->type_id == type_id; }, node); base) {
348 return static_cast<const Type *
>(base->cast(
storage.
data()));
356 template<
typename Type>
358 return const_cast<Type *
>(std::as_const(*this).try_cast<Type>());
375 template<
typename Type>
376 [[nodiscard]]
const Type &
cast()
const {
377 auto *
const actual = try_cast<Type>();
383 template<
typename Type>
385 return const_cast<Type &
>(std::as_const(*this).cast<Type>());
394 template<
typename Type>
397 if(
const auto type_id = internal::meta_info<Type>::resolve()->type_id; node->type_id == type_id) {
399 }
else if(
const auto *
const conv = internal::find_if<&internal::meta_type_node::conv>([type_id](
const auto *curr) {
return curr->type()->type_id == type_id; }, node); conv) {
412 template<
typename Type>
414 bool valid = (node && node->type_id == internal::meta_info<Type>::resolve()->type_id);
417 if(
auto any = std::as_const(*this).
convert<Type>(); any) {
432 template<
typename Type,
typename... Args>
434 *
this =
meta_any{std::in_place_type<Type>, std::forward<Args>(args)...};
446 other.seq_factory = seq_factory;
447 other.assoc_factory = assoc_factory;
480 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
481 return !(node ==
nullptr);
490 return (!node && !other.node) || (node && other.node && node->type_id == other.node->type_id && node->compare(
storage.
data(), other.storage.data()));
500 swap(lhs.storage, rhs.storage);
501 swap(lhs.node, rhs.node);
502 swap(lhs.deref, rhs.deref);
503 swap(lhs.seq_factory, rhs.seq_factory);
504 swap(lhs.assoc_factory, rhs.assoc_factory);
508 internal::meta_storage
storage;
509 internal::meta_type_node *node;
510 dereference_operator_type *deref;
523 return !(lhs == rhs);
543 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_handle>>>
547 if constexpr(std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>,
meta_any>) {
550 static_assert(std::is_lvalue_reference_v<Type>,
"Lvalue reference required");
551 any = std::ref(value);
602 return node->value();
609 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
610 return !(node ==
nullptr);
614 const node_type *node;
632 [[nodiscard]]
inline meta_type parent() const ENTT_NOEXCEPT;
635 [[nodiscard]] inline meta_type type() const ENTT_NOEXCEPT;
642 [[nodiscard]] const
void * cast(const
void *instance) const ENTT_NOEXCEPT {
643 return node->cast(instance);
650 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
651 return !(node ==
nullptr);
655 const node_type *node;
670 [[nodiscard]]
inline meta_type parent() const ENTT_NOEXCEPT;
673 [[nodiscard]] inline meta_type type() const ENTT_NOEXCEPT;
680 [[nodiscard]]
meta_any convert(const
void *instance)
const {
681 return node->conv(instance);
688 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
689 return !(node ==
nullptr);
693 const node_type *node;
710 [[nodiscard]]
inline meta_type parent() const ENTT_NOEXCEPT;
751 template<
typename... Args>
753 std::array<
meta_any,
sizeof...(Args)> arguments{std::forward<Args>(args)...};
754 return invoke(arguments.data(),
sizeof...(Args));
771 internal::meta_range range{node->prop};
772 return std::find_if(range.begin(), range.end(), [&key](
const auto &curr) { return curr.key() == key; }).operator->();
779 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
780 return !(node ==
nullptr);
784 const node_type *node;
804 [[nodiscard]]
inline meta_type parent() const ENTT_NOEXCEPT;
810 [[nodiscard]]
bool is_const() const ENTT_NOEXCEPT {
811 return (node->set ==
nullptr);
819 return node->is_static;
823 [[nodiscard]]
inline meta_type type() const ENTT_NOEXCEPT;
839 template<typename Type>
841 return node->
set && node->set(std::move(instance), std::forward<Type>(value));
854 return node->
get(std::move(instance));
868 internal::meta_range range{node->prop};
869 return std::find_if(range.begin(), range.end(), [&key](
const auto &curr) { return curr.key() == key; }).operator->();
876 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
877 return !(node ==
nullptr);
881 const node_type *node;
903 [[nodiscard]]
inline meta_type parent() const ENTT_NOEXCEPT;
917 [[nodiscard]]
bool is_const() const ENTT_NOEXCEPT {
918 return node->is_const;
926 return node->is_static;
933 [[nodiscard]]
inline meta_type ret() const ENTT_NOEXCEPT;
958 return sz ==
size() ? node->invoke(instance, args) :
meta_any{};
971 template<
typename... Args>
973 std::array<
meta_any,
sizeof...(Args)> arguments{std::forward<Args>(args)...};
974 return invoke(instance, arguments.data(),
sizeof...(Args));
988 internal::meta_range range{node->prop};
989 return std::find_if(range.begin(), range.end(), [&key](
const auto &curr) { return curr.key() == key; }).operator->();
996 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
997 return !(node ==
nullptr);
1001 const node_type *node;
1007 template<
typename... Args, std::size_t... Indexes>
1008 [[nodiscard]]
auto ctor(std::index_sequence<Indexes...>)
const {
1009 internal::meta_range range{node->ctor};
1011 return std::find_if(range.begin(), range.end(), [](
const auto &candidate) {
1012 return candidate.size == sizeof...(Args) && ([](auto *from, auto *to) {
1013 return (from->type_id == to->type_id)
1014 || internal::find_if<&node_type::base>([to](const auto *curr) { return curr->type()->type_id == to->type_id; }, from)
1015 || internal::find_if<&node_type::conv>([to](const auto *curr) { return curr->type()->type_id == to->type_id; }, from);
1016 }(internal::meta_info<Args>::resolve(), candidate.arg(Indexes)) && ...);
1036 return node->type_id;
1051 [[nodiscard]]
bool is_void() const ENTT_NOEXCEPT {
1052 return node->is_void;
1060 return node->is_integral;
1069 return node->is_floating_point;
1077 return node->is_array;
1084 [[nodiscard]]
bool is_enum() const ENTT_NOEXCEPT {
1085 return node->is_enum;
1093 return node->is_union;
1101 return node->is_class;
1109 return node->is_pointer;
1118 return node->is_function_pointer;
1127 return node->is_member_object_pointer;
1137 return node->is_member_function_pointer;
1146 return node->is_pointer_like;
1155 return node->is_sequence_container;
1164 return node->is_associative_container;
1185 return node->extent(dim);
1220 return internal::find_if<&node_type::base>([
id](
const auto *curr) {
1221 return curr->type()->
id ==
id;
1241 template<
typename Type>
1243 return internal::find_if<&node_type::conv>([type_id = internal::meta_info<Type>::resolve()->type_id](
const auto *curr) {
1244 return curr->type()->type_id == type_id;
1261 template<
typename... Args>
1263 return ctor<Args...>(std::index_sequence_for<Args...>{});
1283 return internal::find_if<&node_type::data>([
id](
const auto *curr) {
1284 return curr->id == id;
1305 return internal::find_if<&node_type::func>([
id](
const auto *curr) {
1306 return curr->id == id;
1324 internal::find_if<&node_type::ctor>([args, sz, &any](
const auto *curr) {
1325 return (curr->size == sz) && (any = curr->invoke(args));
1340 template<
typename... Args>
1342 std::array<
meta_any,
sizeof...(Args)> arguments{std::forward<Args>(args)...};
1343 return construct(arguments.data(),
sizeof...(Args));
1363 auto const candidate = func(
id);
1364 return candidate ? candidate.invoke(std::move(instance), args, sz) :
meta_any{};
1378 template<
typename... Args>
1380 std::array<
meta_any,
sizeof...(Args)> arguments{std::forward<Args>(args)...};
1381 return invoke(
id, std::move(instance), arguments.data(),
sizeof...(Args));
1399 template<
typename Type>
1401 auto const candidate = data(
id);
1402 return candidate ? candidate.set(std::move(instance), std::forward<Type>(value)) :
false;
1416 auto const candidate = data(
id);
1417 return candidate ? candidate.get(std::move(instance)) :
meta_any{};
1437 return internal::find_if<&node_type::prop>([key = std::move(key)](
const auto *curr) {
1438 return curr->key() == key;
1446 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
1447 return !(node ==
nullptr);
1457 return (!node && !other.node) || (node && other.node && node->type_id == other.node->type_id);
1471 auto** it = internal::meta_context::global();
1473 while (*it && *it != node) {
1482 [](
auto &&
self,
auto **curr,
auto... member) {
1485 (
self(&(prev->*member)), ...);
1487 prev->next =
nullptr;
1492 unregister_all(&node->prop);
1493 unregister_all(&node->base);
1494 unregister_all(&node->conv);
1495 unregister_all(&node->ctor, &internal::meta_ctor_node::prop);
1496 unregister_all(&node->data, &internal::meta_data_node::prop);
1497 unregister_all(&node->func, &internal::meta_func_node::prop);
1500 node->dtor =
nullptr;
1515 return !(lhs == rhs);
1524 template<
typename... Args>
1526 return type().
invoke(
id, *
this, std::forward<Args>(args)...);
1530 template<
typename Type>
1532 return type().set(
id, *
this, std::forward<Type>(value));
1537 return type().
get(
id, *
this);
1542 return node->parent;
1547 return node->type();
1552 return node->parent;
1557 return node->type();
1562 return node->parent;
1567 return index <
size() ? node->arg(index) :
nullptr;
1572 return node->parent;
1577 return node->type();
1582 return node->parent;
1592 return index <
size() ? node->arg(index) :
nullptr;
1601 template<
typename It>
1606 template<
typename It>
1608 if constexpr(std::is_const_v<std::remove_reference_t<decltype(*std::declval<It>())>>) {
1609 return *any.
cast<It>();
1611 return std::ref(*any.
cast<It>());
1635 template<typename It>
1637 : next_fn{&incr<It>},
1644 return next_fn(
handle.ref()), *
this;
1650 return ++(*this), orig;
1660 return handle == other.handle;
1670 return !(*
this == other);
1678 return get_fn(
handle.ref());
1685 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
1686 return static_cast<bool>(
handle);
1696 template<
typename Type>
1697 struct meta_sequence_container::meta_sequence_container_proxy {
1701 return internal::meta_info<typename traits_type::value_type>::resolve();
1704 [[nodiscard]]
static size_type size(
const void *container) ENTT_NOEXCEPT {
1705 return traits_type::size(*
static_cast<const Type *
>(container));
1709 return traits_type::resize(*
static_cast<Type *
>(container), sz);
1712 [[nodiscard]]
static bool clear(
void *container) {
1713 return traits_type::clear(*
static_cast<Type *
>(container));
1717 return iterator{traits_type::begin(*
static_cast<Type *
>(container))};
1720 [[nodiscard]]
static iterator end(
void *container) {
1721 return iterator{traits_type::end(*
static_cast<Type *
>(container))};
1724 [[nodiscard]]
static std::pair<iterator, bool>
insert(
void *container,
iterator it, meta_any value) {
1725 if(
const auto *v_ptr = value.try_cast<
typename traits_type::value_type>(); v_ptr || value.convert<
typename traits_type::value_type>()) {
1726 auto ret = traits_type::insert(*
static_cast<Type *
>(container), it.handle.cast<
typename traits_type::iterator>(), v_ptr ? *v_ptr : value.cast<
typename traits_type::value_type>());
1727 return {
iterator{std::move(ret.first)}, ret.second};
1733 [[nodiscard]]
static std::pair<iterator, bool>
erase(
void *container,
iterator it) {
1734 auto ret = traits_type::erase(*
static_cast<Type *
>(container), it.handle.cast<
typename traits_type::iterator>());
1735 return {
iterator{std::move(ret.first)}, ret.second};
1738 [[nodiscard]]
static meta_any
get(
void *container,
size_type pos) {
1739 return std::ref(traits_type::get(*
static_cast<Type *
>(container), pos));
1749 return value_type_fn();
1758 return size_fn(instance);
1768 return resize_fn(instance, sz);
1777 return clear_fn(instance);
1786 return begin_fn(instance);
1797 return end_fn(instance);
1809 return insert_fn(instance, it, value.
ref());
1821 return erase_fn(instance, it);
1832 return get_fn(instance, pos);
1840 [[nodiscard]]
inline meta_sequence_container::operator bool() const ENTT_NOEXCEPT {
1841 return (instance !=
nullptr);
1847 template<
typename It>
1852 template<
bool KeyOnly,
typename It>
1854 if constexpr(KeyOnly) {
1855 return *any.
cast<It>();
1857 return any.
cast<It>()->first;
1861 template<
bool KeyOnly,
typename It>
1863 if constexpr(KeyOnly) {
1866 return std::ref(any.cast<It>()->second);
1892 template<
bool KeyOnly, typename It>
1894 : next_fn{&incr<It>},
1895 key_fn{&key<KeyOnly, It>},
1896 value_fn{&value<KeyOnly, It>},
1902 return next_fn(
handle.ref()), *
this;
1908 return ++(*this), orig;
1918 return handle == other.handle;
1928 return !(*
this == other);
1936 return { key_fn(
handle.ref()), value_fn(
handle.ref()) };
1943 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
1944 return static_cast<bool>(
handle);
1955 template<
typename Type>
1956 struct meta_associative_container::meta_associative_container_proxy {
1959 [[nodiscard]]
static meta_type key_type() ENTT_NOEXCEPT {
1960 return internal::meta_info<typename traits_type::key_type>::resolve();
1963 [[nodiscard]]
static meta_type mapped_type() ENTT_NOEXCEPT {
1964 if constexpr(is_key_only_meta_associative_container_v<Type>) {
1967 return internal::meta_info<typename traits_type::mapped_type>::resolve();
1971 [[nodiscard]]
static meta_type
value_type() ENTT_NOEXCEPT {
1972 return internal::meta_info<typename traits_type::value_type>::resolve();
1975 [[nodiscard]]
static size_type size(
const void *container) ENTT_NOEXCEPT {
1976 return traits_type::size(*
static_cast<const Type *
>(container));
1979 [[nodiscard]]
static bool clear(
void *container) {
1980 return traits_type::clear(*
static_cast<Type *
>(container));
1984 return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::begin(*
static_cast<Type *
>(container))};
1987 [[nodiscard]]
static iterator end(
void *container) {
1988 return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::end(*
static_cast<Type *
>(container))};
1991 [[nodiscard]]
static bool insert(
void *container, meta_any key, meta_any value) {
1992 if(
const auto *k_ptr = key.try_cast<
typename traits_type::key_type>(); k_ptr || key.convert<
typename traits_type::key_type>()) {
1993 if constexpr(is_key_only_meta_associative_container_v<Type>) {
1994 return traits_type::insert(*
static_cast<Type *
>(container), k_ptr ? *k_ptr : key.cast<
typename traits_type::key_type>());
1996 if(
auto *m_ptr = value.try_cast<
typename traits_type::mapped_type>(); m_ptr || value.convert<
typename traits_type::mapped_type>()) {
1997 return traits_type::insert(*
static_cast<Type *
>(container), k_ptr ? *k_ptr : key.cast<
typename traits_type::key_type>(), m_ptr ? *m_ptr : value.cast<
typename traits_type::mapped_type>());
2005 [[nodiscard]]
static bool erase(
void *container, meta_any key) {
2006 if(
const auto *k_ptr = key.try_cast<
typename traits_type::key_type>(); k_ptr || key.convert<
typename traits_type::key_type>()) {
2007 return traits_type::erase(*
static_cast<Type *
>(container), k_ptr ? *k_ptr : key.cast<
typename traits_type::key_type>());
2013 [[nodiscard]]
static iterator find(
void *container, meta_any key) {
2014 if(
const auto *k_ptr = key.try_cast<
typename traits_type::key_type>(); k_ptr || key.convert<
typename traits_type::key_type>()) {
2015 return iterator{is_key_only_meta_associative_container<Type>{}, traits_type::find(*
static_cast<Type *
>(container), k_ptr ? *k_ptr : key.cast<
typename traits_type::key_type>())};
2029 return key_only_container;
2038 return key_type_fn();
2047 return mapped_type_fn();
2053 return value_type_fn();
2059 return size_fn(instance);
2065 return clear_fn(instance);
2071 return begin_fn(instance);
2077 return end_fn(instance);
2088 return insert_fn(instance, key.
ref(), value.
ref());
2098 return erase_fn(instance, key.
ref());
2109 return find_fn(instance, key.
ref());
2117 [[nodiscard]]
inline meta_associative_container::operator bool() const ENTT_NOEXCEPT {
2118 return (instance !=
nullptr);
constexpr get_t< Type... > get
Variable template for lists of observed components.
Non-owning handle to an entity.
basic_handle< entity > handle
Alias declaration for the most common use case.
std::uint32_t id_type
Alias declaration for type identifiers.
std::integral_constant< decltype(Value), Value > integral_constant
Wraps a static constant.
const entity_type * data() const noexcept
Direct access to the internal packed array.
Basic implementation of a y-combinator.
Basic storage implementation.
void invoke(basic_registry< Entity > ®, const Entity entt)
Helper to create a listener that directly invokes a member function.
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.