1 #ifndef ENTT_META_INTERNAL_HPP
2 #define ENTT_META_INTERNAL_HPP
10 #include "../core/attribute.h"
11 #include "../config/config.h"
12 #include "../core/fwd.hpp"
13 #include "../core/type_info.hpp"
14 #include "../core/type_traits.hpp"
15 #include "type_traits.hpp"
35 using storage_type = std::aligned_storage_t<
sizeof(
void *),
alignof(
void *)>;
36 using copy_fn_type = void(meta_storage &,
const meta_storage &);
37 using steal_fn_type = void(meta_storage &, meta_storage &);
38 using destroy_fn_type = void(meta_storage &);
40 template<
typename Type,
typename = std::
void_t<>>
42 template<
typename... Args>
43 static void instance(meta_storage &buffer, Args &&... args) {
44 buffer.instance =
new Type{std::forward<Args>(args)...};
45 new (&buffer.storage) Type *{
static_cast<Type *
>(buffer.instance)};
48 static void destroy(meta_storage &buffer) {
49 delete static_cast<Type *
>(buffer.instance);
52 static void copy(meta_storage &to,
const meta_storage &from) {
53 to.instance =
new Type{*
static_cast<const Type *
>(from.instance)};
54 new (&to.storage) Type *{
static_cast<Type *
>(to.instance)};
57 static void steal(meta_storage &to, meta_storage &from) {
58 new (&to.storage) Type *{
static_cast<Type *
>(from.instance)};
59 to.instance = from.instance;
63 template<
typename Type>
64 struct type_traits<Type, std::enable_if_t<sizeof(Type) <= sizeof(void *) && std::is_nothrow_move_constructible_v<Type>>> {
65 template<
typename... Args>
66 static void instance(meta_storage &buffer, Args &&... args) {
67 buffer.instance =
new (&buffer.storage) Type{std::forward<Args>(args)...};
70 static void destroy(meta_storage &buffer) {
71 static_cast<Type *
>(buffer.instance)->~Type();
74 static void copy(meta_storage &to,
const meta_storage &from) {
75 to.instance =
new (&to.storage) Type{*
static_cast<const Type *
>(from.instance)};
78 static void steal(meta_storage &to, meta_storage &from) {
79 to.instance =
new (&to.storage) Type{std::move(*
static_cast<Type *
>(from.instance))};
86 meta_storage() ENTT_NOEXCEPT
94 template<
typename Type,
typename... Args>
95 explicit meta_storage(std::in_place_type_t<Type>, [[maybe_unused]] Args &&... args)
98 if constexpr(!std::is_void_v<Type>) {
99 type_traits<Type>::instance(*
this, std::forward<Args>(args)...);
100 destroy_fn = &type_traits<Type>::destroy;
101 copy_fn = &type_traits<Type>::copy;
102 steal_fn = &type_traits<Type>::steal;
106 template<
typename Type>
107 meta_storage(std::reference_wrapper<Type> value)
110 instance = &value.get();
113 template<
typename Type,
typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, meta_storage>>>
114 meta_storage(Type &&value)
115 : meta_storage{std::in_place_type<std::remove_cv_t<std::remove_reference_t<Type>>>, std::forward<Type>(value)}
118 meta_storage(
const meta_storage &other)
121 (other.copy_fn ? other.copy_fn : [](
auto &to,
const auto &from) { to.instance = from.instance; })(*
this, other);
122 destroy_fn = other.destroy_fn;
123 copy_fn = other.copy_fn;
124 steal_fn = other.steal_fn;
127 meta_storage(meta_storage &&other)
139 meta_storage & operator=(meta_storage other) {
144 [[nodiscard]]
const void * data() const ENTT_NOEXCEPT {
148 [[nodiscard]]
void * data() ENTT_NOEXCEPT {
149 return const_cast<void *
>(std::as_const(*this).data());
152 template<
typename Type,
typename... Args>
153 void emplace(Args &&... args) {
154 *
this = meta_storage{std::in_place_type<Type>, std::forward<Args>(args)...};
157 [[nodiscard]] meta_storage ref() const ENTT_NOEXCEPT {
158 meta_storage other{};
159 other.instance = instance;
163 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
164 return !(instance ==
nullptr);
167 friend void swap(meta_storage &lhs, meta_storage &rhs) {
170 if(lhs.steal_fn && rhs.steal_fn) {
171 meta_storage buffer{};
172 lhs.steal_fn(buffer, lhs);
173 rhs.steal_fn(lhs, rhs);
174 lhs.steal_fn(rhs, buffer);
175 }
else if(lhs.steal_fn) {
176 lhs.steal_fn(rhs, lhs);
177 }
else if(rhs.steal_fn) {
178 rhs.steal_fn(lhs, rhs);
180 swap(lhs.instance, rhs.instance);
183 swap(lhs.destroy_fn, rhs.destroy_fn);
184 swap(lhs.copy_fn, rhs.copy_fn);
185 swap(lhs.steal_fn, rhs.steal_fn);
189 storage_type storage;
191 destroy_fn_type *destroy_fn;
192 copy_fn_type *copy_fn;
193 steal_fn_type *steal_fn;
197 struct meta_type_node;
200 struct meta_prop_node {
201 meta_prop_node * next;
202 meta_any(*
const key)();
203 meta_any(*
const value)();
207 struct meta_base_node {
208 meta_type_node *
const parent;
209 meta_base_node * next;
210 meta_type_node *(*
const type)() ENTT_NOEXCEPT;
211 const
void *(* const cast)(const
void *) ENTT_NOEXCEPT;
215 struct meta_conv_node {
216 meta_type_node *
const parent;
217 meta_conv_node * next;
218 meta_type_node *(*
const type)() ENTT_NOEXCEPT;
219 meta_any(* const conv)(const
void *);
223 struct meta_ctor_node {
224 using size_type = std::size_t;
225 meta_type_node *
const parent;
226 meta_ctor_node * next;
227 meta_prop_node * prop;
228 const size_type size;
229 meta_type_node *(*
const arg)(size_type) ENTT_NOEXCEPT;
230 meta_any(*
const invoke)(meta_any *
const);
234 struct meta_data_node {
236 meta_type_node *
const parent;
237 meta_data_node * next;
238 meta_prop_node * prop;
239 const bool is_static;
240 meta_type_node *(*
const type)() ENTT_NOEXCEPT;
241 bool(* const set)(meta_handle, meta_any);
242 meta_any(* const
get)(meta_handle);
246 struct meta_func_node {
247 using size_type = std::size_t;
249 meta_type_node *
const parent;
250 meta_func_node * next;
251 meta_prop_node * prop;
252 const size_type size;
254 const bool is_static;
255 meta_type_node *(*
const ret)() ENTT_NOEXCEPT;
256 meta_type_node *(* const arg)(size_type) ENTT_NOEXCEPT;
257 meta_any(* const
invoke)(meta_handle, meta_any *);
261 struct meta_type_node {
262 using size_type = std::size_t;
265 meta_type_node * next;
266 meta_prop_node * prop;
268 const bool is_integral;
269 const bool is_floating_point;
274 const bool is_pointer;
275 const bool is_function_pointer;
276 const bool is_member_object_pointer;
277 const bool is_member_function_pointer;
278 const bool is_pointer_like;
279 const bool is_sequence_container;
280 const bool is_associative_container;
281 const size_type rank;
282 size_type(*
const extent)(size_type);
283 bool(*
const compare)(
const void *,
const void *);
284 meta_type_node *(*
const remove_pointer)() ENTT_NOEXCEPT;
285 meta_type_node *(* const remove_extent)() ENTT_NOEXCEPT;
286 meta_base_node *base{
nullptr};
287 meta_conv_node *conv{
nullptr};
288 meta_ctor_node *ctor{
nullptr};
289 meta_data_node *data{
nullptr};
290 meta_func_node *func{
nullptr};
291 void(* dtor)(
void *){
nullptr};
295 template<
typename Node>
297 struct range_iterator {
298 using difference_type = std::ptrdiff_t;
299 using value_type = Node;
300 using pointer = value_type *;
301 using reference = value_type &;
302 using iterator_category = std::forward_iterator_tag;
304 range_iterator() ENTT_NOEXCEPT = default;
306 range_iterator(Node *head) ENTT_NOEXCEPT
310 range_iterator & operator++() ENTT_NOEXCEPT {
311 return node = node->next, *
this;
314 range_iterator operator++(
int) ENTT_NOEXCEPT {
315 range_iterator orig = *
this;
316 return ++(*this), orig;
319 [[nodiscard]]
bool operator==(
const range_iterator &other)
const ENTT_NOEXCEPT {
320 return other.node == node;
323 [[nodiscard]]
bool operator!=(
const range_iterator &other)
const ENTT_NOEXCEPT {
324 return !(*
this == other);
327 [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
331 [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
332 return *operator->();
340 using iterator = range_iterator;
342 meta_range() ENTT_NOEXCEPT = default;
344 meta_range(Node *head)
348 [[nodiscard]] iterator begin() const ENTT_NOEXCEPT {
349 return iterator{node};
352 [[nodiscard]] iterator end() const ENTT_NOEXCEPT {
361 template<auto Member,
typename Op>
362 auto find_if(
const Op &op,
const meta_type_node *node)
363 -> std::decay_t<decltype(node->*Member)> {
364 std::decay_t<decltype(node->*Member)> ret =
nullptr;
366 for(
auto &&curr: meta_range{node->*Member}) {
374 for(
auto &&curr: meta_range{node->base}) {
375 if(ret = find_if<Member>(op, curr.type()); ret) {
385 template<
typename Type>
386 class ENTT_API meta_node {
387 static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>,
"Invalid type");
389 [[nodiscard]]
static bool compare(
const void *lhs,
const void *rhs) {
390 if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
391 return *
static_cast<const Type *
>(lhs) == *
static_cast<const Type *
>(rhs);
397 template<std::size_t... Index>
398 [[nodiscard]]
static auto extent(meta_type_node::size_type dim, std::index_sequence<Index...>) {
399 meta_type_node::size_type ext{};
400 ((ext = (dim == Index ? std::extent_v<Type, Index> : ext)), ...);
405 [[nodiscard]]
static meta_type_node *
resolve() ENTT_NOEXCEPT {
406 static meta_type_node node{
411 std::is_void_v<Type>,
412 std::is_integral_v<Type>,
413 std::is_floating_point_v<Type>,
414 std::is_array_v<Type>,
415 std::is_enum_v<Type>,
416 std::is_union_v<Type>,
417 std::is_class_v<Type>,
418 std::is_pointer_v<Type>,
419 std::is_pointer_v<Type> && std::is_function_v<std::remove_pointer_t<Type>>,
420 std::is_member_object_pointer_v<Type>,
421 std::is_member_function_pointer_v<Type>,
422 is_meta_pointer_like_v<Type>,
423 has_meta_sequence_container_traits_v<Type>,
424 has_meta_associative_container_traits_v<Type>,
426 [](meta_type_node::size_type dim) {
427 return extent(dim, std::make_index_sequence<std::rank_v<Type>>{});
430 &meta_node<std::remove_const_t<std::remove_pointer_t<Type>>>
::resolve,
431 &meta_node<std::remove_const_t<std::remove_extent_t<Type>>>
::resolve
439 template<
typename... Type>
440 struct meta_info: meta_node<std::remove_cv_t<std::remove_reference_t<Type>>...> {};