1#ifndef ENTT_META_NODE_HPP
2#define ENTT_META_NODE_HPP
8#include "../config/config.h"
9#include "../container/dense_map.hpp"
10#include "../core/attribute.h"
11#include "../core/enum.hpp"
12#include "../core/fwd.hpp"
13#include "../core/type_info.hpp"
14#include "../core/type_traits.hpp"
15#include "../core/utility.hpp"
17#include "type_traits.hpp"
28enum class meta_traits : std::uint32_t {
32 is_arithmetic = 0x0004,
38 is_meta_pointer_like = 0x0100,
39 is_meta_sequence_container = 0x0200,
40 is_meta_associative_container = 0x0400,
46struct meta_prop_node {
47 meta_type_node (*type)(
const meta_context &)
noexcept {};
48 std::shared_ptr<void> value{};
51struct meta_base_node {
52 meta_type_node (*type)(
const meta_context &)
noexcept {};
53 const void *(*cast)(
const void *)
noexcept {};
56struct meta_conv_node {
57 meta_any (*conv)(
const meta_ctx &,
const void *){};
60struct meta_ctor_node {
61 using size_type = std::size_t;
64 meta_type (*arg)(
const meta_ctx &,
const size_type)
noexcept {};
65 meta_any (*invoke)(
const meta_ctx &, meta_any *
const){};
68struct meta_dtor_node {
69 void (*dtor)(
void *){};
72struct meta_data_node {
73 using size_type = std::size_t;
75 meta_traits traits{meta_traits::is_none};
77 meta_type_node (*type)(
const meta_context &)
noexcept {};
78 meta_type (*arg)(
const meta_ctx &,
const size_type)
noexcept {};
79 bool (*set)(meta_handle, meta_any){};
80 meta_any (*get)(
const meta_ctx &, meta_handle){};
81 dense_map<id_type, meta_prop_node, identity> prop{};
84struct meta_func_node {
85 using size_type = std::size_t;
87 meta_traits traits{meta_traits::is_none};
89 meta_type_node (*ret)(
const meta_context &)
noexcept {};
90 meta_type (*arg)(
const meta_ctx &,
const size_type)
noexcept {};
91 meta_any (*invoke)(
const meta_ctx &, meta_handle, meta_any *
const){};
92 std::shared_ptr<meta_func_node> next{};
93 dense_map<id_type, meta_prop_node, identity> prop{};
96struct meta_template_node {
97 using size_type = std::size_t;
100 meta_type_node (*type)(
const meta_context &)
noexcept {};
101 meta_type_node (*arg)(
const meta_context &,
const size_type)
noexcept {};
104struct meta_type_descriptor {
105 dense_map<id_type, meta_ctor_node, identity> ctor{};
106 dense_map<id_type, meta_base_node, identity> base{};
107 dense_map<id_type, meta_conv_node, identity> conv{};
108 dense_map<id_type, meta_data_node, identity> data{};
109 dense_map<id_type, meta_func_node, identity> func{};
110 dense_map<id_type, meta_prop_node, identity> prop{};
113struct meta_type_node {
114 using size_type = std::size_t;
116 const type_info *info{};
118 meta_traits traits{meta_traits::is_none};
119 size_type size_of{0u};
120 meta_type_node (*resolve)(
const meta_context &)
noexcept {};
121 meta_type_node (*remove_pointer)(
const meta_context &)
noexcept {};
122 meta_any (*default_constructor)(
const meta_ctx &){};
123 double (*conversion_helper)(
void *,
const void *){};
124 meta_any (*from_void)(
const meta_ctx &,
void *,
const void *){};
125 meta_template_node templ{};
126 meta_dtor_node dtor{};
127 std::shared_ptr<meta_type_descriptor> details{};
131auto *look_for(
const meta_context &context,
const meta_type_node &node,
const id_type
id) {
133 if(
const auto it = (node.details.get()->*Member).find(
id); it != (node.details.get()->*Member).cend()) {
137 for(
auto &&curr: node.details->base) {
138 if(
auto *elem = look_for<Member>(context, curr.second.type(context),
id); elem) {
144 return static_cast<typename std::remove_reference_t<decltype(node.details.
get()-
>*Member)>::mapped_type *>(
nullptr);
147template<
typename Type>
148meta_type_node
resolve(
const meta_context &)
noexcept;
150template<
typename... Args>
151[[nodiscard]]
auto meta_arg_node(
const meta_context &context, type_list<Args...>, [[maybe_unused]]
const std::size_t index)
noexcept {
152 [[maybe_unused]] std::size_t pos{};
153 meta_type_node (*value)(
const meta_context &)
noexcept =
nullptr;
154 ((value = (pos++ == index ? &resolve<std::remove_cv_t<std::remove_reference_t<Args>>> : value)), ...);
155 ENTT_ASSERT(value !=
nullptr,
"Out of bounds");
156 return value(context);
159[[nodiscard]]
inline const void *try_cast(
const meta_context &context,
const meta_type_node &from,
const meta_type_node &to,
const void *instance)
noexcept {
160 if(from.info && to.info && *from.info == *to.info) {
165 for(
auto &&curr: from.details->base) {
166 if(
const void *elem = try_cast(context, curr.second.type(context), to, curr.second.cast(instance)); elem) {
175template<
typename Func>
176[[nodiscard]]
inline auto try_convert(
const meta_context &context,
const meta_type_node &from,
const type_info &to,
const bool arithmetic_or_enum,
const void *instance, Func func) {
177 if(from.info && *from.info == to) {
178 return func(instance, from);
182 if(
auto it = from.details->conv.find(to.hash()); it != from.details->conv.cend()) {
183 return func(instance, it->second);
186 for(
auto &&curr: from.details->base) {
187 if(
auto other = try_convert(context, curr.second.type(context), to, arithmetic_or_enum, curr.second.cast(instance), func); other) {
193 if(from.conversion_helper && arithmetic_or_enum) {
194 return func(instance, from.conversion_helper);
197 return func(instance);
200[[nodiscard]]
inline const meta_type_node *try_resolve(
const meta_context &context,
const type_info &info)
noexcept {
201 const auto it = context.value.find(info.hash());
202 return it != context.value.end() ? &it->second :
nullptr;
205template<
typename Type>
206[[nodiscard]] meta_type_node
resolve(
const meta_context &context)
noexcept {
207 static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>,
"Invalid type");
209 if(
auto *elem = try_resolve(context, type_id<Type>()); elem) {
215 type_id<Type>().hash(),
216 (std::is_arithmetic_v<Type> ? meta_traits::is_arithmetic : meta_traits::is_none)
217 | (std::is_integral_v<Type> ? meta_traits::is_integral : meta_traits::is_none)
218 | (std::is_signed_v<Type> ? meta_traits::is_signed : meta_traits::is_none)
219 | (std::is_array_v<Type> ? meta_traits::is_array : meta_traits::is_none)
220 | (std::is_enum_v<Type> ? meta_traits::is_enum : meta_traits::is_none)
221 | (std::is_class_v<Type> ? meta_traits::is_class : meta_traits::is_none)
223 | (
is_complete_v<meta_sequence_container_traits<Type>> ? meta_traits::is_meta_sequence_container : meta_traits::is_none)
224 | (
is_complete_v<meta_associative_container_traits<Type>> ? meta_traits::is_meta_associative_container : meta_traits::is_none),
227 &
resolve<std::remove_cv_t<std::remove_pointer_t<Type>>>};
229 if constexpr(std::is_default_constructible_v<Type>) {
230 node.default_constructor = +[](
const meta_ctx &ctx) {
231 return meta_any{ctx, std::in_place_type<Type>};
235 if constexpr(std::is_arithmetic_v<Type>) {
236 node.conversion_helper = +[](
void *bin,
const void *value) {
237 return bin ?
static_cast<double>(*
static_cast<Type *
>(bin) =
static_cast<Type
>(*
static_cast<const double *
>(value))) : static_cast<double>(*static_cast<const Type *>(value));
239 }
else if constexpr(std::is_enum_v<Type>) {
240 node.conversion_helper = +[](
void *bin,
const void *value) {
241 return bin ?
static_cast<double>(*
static_cast<Type *
>(bin) =
static_cast<Type
>(
static_cast<std::underlying_type_t<Type>
>(*
static_cast<const double *
>(value)))) : static_cast<double>(*static_cast<const Type *>(value));
245 if constexpr(!std::is_void_v<Type> && !std::is_function_v<Type>) {
246 node.from_void = +[](
const meta_ctx &ctx,
void *element,
const void *as_const) {
248 return meta_any{ctx, std::in_place_type<std::decay_t<Type> &>, *
static_cast<std::decay_t<Type> *
>(element)};
251 return meta_any{ctx, std::in_place_type<const std::decay_t<Type> &>, *
static_cast<const std::decay_t<Type> *
>(as_const)};
255 if constexpr(is_complete_v<meta_template_traits<Type>>) {
256 node.templ = meta_template_node{
257 meta_template_traits<Type>::args_type::size,
258 &resolve<typename meta_template_traits<Type>::class_type>,
259 +[](
const meta_context &area,
const std::size_t index)
noexcept {
return meta_arg_node(area,
typename meta_template_traits<Type>::args_type{}, index); }};
constexpr std::size_t size_of_v
Helper variable template.
std::uint32_t id_type
Alias declaration for type identifiers.
constexpr bool is_complete_v
Helper variable template.
constexpr get_t< Type... > get
Variable template for lists of observed components.
constexpr auto is_meta_pointer_like_v
Helper variable template.
meta_type resolve(const meta_ctx &ctx) noexcept
Returns the meta type associated with a given type.