meta: overall improvements
This commit is contained in:
@@ -64,7 +64,7 @@ class meta_factory {
|
||||
[]() -> meta_any {
|
||||
return std::get<1>(prop);
|
||||
},
|
||||
[]() -> meta_prop {
|
||||
[]() ENTT_NOEXCEPT -> meta_prop {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
@@ -93,11 +93,11 @@ class meta_factory {
|
||||
std::is_member_object_pointer_v<Type>,
|
||||
std::is_member_function_pointer_v<Type>,
|
||||
std::extent_v<Type>,
|
||||
[]() -> meta_type {
|
||||
[]() ENTT_NOEXCEPT -> meta_type {
|
||||
return internal::meta_info<std::remove_pointer_t<Type>>::resolve();
|
||||
},
|
||||
&internal::destroy<Type>,
|
||||
[]() -> meta_type {
|
||||
[]() ENTT_NOEXCEPT -> meta_type {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
@@ -209,10 +209,10 @@ public:
|
||||
type,
|
||||
nullptr,
|
||||
&internal::meta_info<Base>::resolve,
|
||||
[](void *instance) -> void * {
|
||||
[](void *instance) ENTT_NOEXCEPT -> void * {
|
||||
return static_cast<Base *>(static_cast<Type *>(instance));
|
||||
},
|
||||
[]() -> meta_base {
|
||||
[]() ENTT_NOEXCEPT -> meta_base {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
@@ -247,7 +247,7 @@ public:
|
||||
[](void *instance) -> meta_any {
|
||||
return static_cast<To>(*static_cast<Type *>(instance));
|
||||
},
|
||||
[]() -> meta_conv {
|
||||
[]() ENTT_NOEXCEPT -> meta_conv {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
@@ -290,7 +290,7 @@ public:
|
||||
[](meta_any * const any) {
|
||||
return internal::invoke<Type, Func>(nullptr, any, std::make_index_sequence<helper_type::size>{});
|
||||
},
|
||||
[]() -> meta_ctor {
|
||||
[]() ENTT_NOEXCEPT -> meta_ctor {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
@@ -331,7 +331,7 @@ public:
|
||||
[](meta_any * const any) {
|
||||
return internal::construct<Type, Args...>(any, std::make_index_sequence<helper_type::size>{});
|
||||
},
|
||||
[]() -> meta_ctor {
|
||||
[]() ENTT_NOEXCEPT -> meta_ctor {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
@@ -374,7 +374,7 @@ public:
|
||||
? ((*Func)(static_cast<Type *>(handle.data())), true)
|
||||
: false;
|
||||
},
|
||||
[]() -> meta_dtor {
|
||||
[]() ENTT_NOEXCEPT -> meta_dtor {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
@@ -418,7 +418,7 @@ public:
|
||||
&internal::meta_info<Type>::resolve,
|
||||
[](meta_handle, meta_any, meta_any) { return false; },
|
||||
[](meta_handle, meta_any) -> meta_any { return Data; },
|
||||
[]() -> meta_data {
|
||||
[]() ENTT_NOEXCEPT -> meta_data {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
@@ -439,7 +439,7 @@ public:
|
||||
&internal::meta_info<data_type>::resolve,
|
||||
&internal::setter<std::is_const_v<data_type>, Type, Data>,
|
||||
&internal::getter<Type, Data>,
|
||||
[]() -> meta_data {
|
||||
[]() ENTT_NOEXCEPT -> meta_data {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
@@ -461,7 +461,7 @@ public:
|
||||
&internal::meta_info<data_type>::resolve,
|
||||
&internal::setter<std::is_const_v<data_type>, Type, Data>,
|
||||
&internal::getter<Type, Data>,
|
||||
[]() -> meta_data {
|
||||
[]() ENTT_NOEXCEPT -> meta_data {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
@@ -519,7 +519,7 @@ public:
|
||||
&internal::meta_info<underlying_type>::resolve,
|
||||
&internal::setter<false, Type, Setter>,
|
||||
&internal::getter<Type, Getter>,
|
||||
[]() -> meta_data {
|
||||
[]() ENTT_NOEXCEPT -> meta_data {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
@@ -569,7 +569,7 @@ public:
|
||||
[](meta_handle handle, meta_any *any) {
|
||||
return internal::invoke<Type, Func>(handle, any, std::make_index_sequence<func_type::size>{});
|
||||
},
|
||||
[]() -> meta_func {
|
||||
[]() ENTT_NOEXCEPT -> meta_func {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,7 +44,7 @@ struct meta_prop_node {
|
||||
meta_prop_node * next;
|
||||
meta_any(* const key)();
|
||||
meta_any(* const value)();
|
||||
meta_prop(* const meta)();
|
||||
meta_prop(* const meta)() ENTT_NOEXCEPT;
|
||||
};
|
||||
|
||||
|
||||
@@ -52,9 +52,9 @@ struct meta_base_node {
|
||||
meta_base_node ** const underlying;
|
||||
meta_type_node * const parent;
|
||||
meta_base_node * next;
|
||||
meta_type_node *(* const type)();
|
||||
void *(* const cast)(void *);
|
||||
meta_base(* const meta)();
|
||||
meta_type_node *(* const type)() ENTT_NOEXCEPT;
|
||||
void *(* const cast)(void *) ENTT_NOEXCEPT;
|
||||
meta_base(* const meta)() ENTT_NOEXCEPT;
|
||||
};
|
||||
|
||||
|
||||
@@ -62,9 +62,9 @@ struct meta_conv_node {
|
||||
meta_conv_node ** const underlying;
|
||||
meta_type_node * const parent;
|
||||
meta_conv_node * next;
|
||||
meta_type_node *(* const type)();
|
||||
meta_type_node *(* const type)() ENTT_NOEXCEPT;
|
||||
meta_any(* const conv)(void *);
|
||||
meta_conv(* const meta)();
|
||||
meta_conv(* const meta)() ENTT_NOEXCEPT;
|
||||
};
|
||||
|
||||
|
||||
@@ -75,9 +75,9 @@ struct meta_ctor_node {
|
||||
meta_ctor_node * next;
|
||||
meta_prop_node * prop;
|
||||
const size_type size;
|
||||
meta_type_node *(* const arg)(size_type);
|
||||
meta_type_node *(* const arg)(size_type) ENTT_NOEXCEPT;
|
||||
meta_any(* const invoke)(meta_any * const);
|
||||
meta_ctor(* const meta)();
|
||||
meta_ctor(* const meta)() ENTT_NOEXCEPT;
|
||||
};
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ struct meta_dtor_node {
|
||||
meta_dtor_node ** const underlying;
|
||||
meta_type_node * const parent;
|
||||
bool(* const invoke)(meta_handle);
|
||||
meta_dtor(* const meta)();
|
||||
meta_dtor(* const meta)() ENTT_NOEXCEPT;
|
||||
};
|
||||
|
||||
|
||||
@@ -97,10 +97,10 @@ struct meta_data_node {
|
||||
meta_prop_node * prop;
|
||||
const bool is_const;
|
||||
const bool is_static;
|
||||
meta_type_node *(* const type)();
|
||||
meta_type_node *(* const type)() ENTT_NOEXCEPT;
|
||||
bool(* const set)(meta_handle, meta_any, meta_any);
|
||||
meta_any(* const get)(meta_handle, meta_any);
|
||||
meta_data(* const meta)();
|
||||
meta_data(* const meta)() ENTT_NOEXCEPT;
|
||||
};
|
||||
|
||||
|
||||
@@ -114,10 +114,10 @@ struct meta_func_node {
|
||||
const size_type size;
|
||||
const bool is_const;
|
||||
const bool is_static;
|
||||
meta_type_node *(* const ret)();
|
||||
meta_type_node *(* const arg)(size_type);
|
||||
meta_type_node *(* const ret)() ENTT_NOEXCEPT;
|
||||
meta_type_node *(* const arg)(size_type) ENTT_NOEXCEPT;
|
||||
meta_any(* const invoke)(meta_handle, meta_any *);
|
||||
meta_func(* const meta)();
|
||||
meta_func(* const meta)() ENTT_NOEXCEPT;
|
||||
};
|
||||
|
||||
|
||||
@@ -138,9 +138,9 @@ struct meta_type_node {
|
||||
const bool is_member_object_pointer;
|
||||
const bool is_member_function_pointer;
|
||||
const size_type extent;
|
||||
meta_type(* const remove_pointer)();
|
||||
meta_type(* const remove_pointer)() ENTT_NOEXCEPT;
|
||||
bool(* const destroy)(meta_handle);
|
||||
meta_type(* const meta)();
|
||||
meta_type(* const meta)() ENTT_NOEXCEPT;
|
||||
meta_base_node *base{nullptr};
|
||||
meta_conv_node *conv{nullptr};
|
||||
meta_ctor_node *ctor{nullptr};
|
||||
@@ -303,23 +303,24 @@ class meta_any {
|
||||
friend class meta_handle;
|
||||
|
||||
using storage_type = std::aligned_storage_t<sizeof(void *), alignof(void *)>;
|
||||
using compare_fn_type = bool(*)(const void *, const void *);
|
||||
using copy_fn_type = void *(*)(storage_type &, const void *);
|
||||
using destroy_fn_type = void(*)(storage_type &);
|
||||
using compare_fn_type = bool(const void *, const void *) ENTT_NOEXCEPT;
|
||||
using copy_fn_type = void *(storage_type &, const void *);
|
||||
using destroy_fn_type = void(storage_type &);
|
||||
using steal_fn_type = void *(storage_type &, storage_type &, destroy_fn_type *, void *) ENTT_NOEXCEPT;
|
||||
|
||||
template<typename Type>
|
||||
static auto compare(int, const Type &lhs, const Type &rhs)
|
||||
static auto compare(int, const Type &lhs, const Type &rhs) ENTT_NOEXCEPT
|
||||
-> decltype(lhs == rhs, bool{}) {
|
||||
return lhs == rhs;
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
static bool compare(char, const Type &lhs, const Type &rhs) {
|
||||
static bool compare(char, const Type &lhs, const Type &rhs) ENTT_NOEXCEPT {
|
||||
return &lhs == &rhs;
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
static bool compare(const void *lhs, const void *rhs) {
|
||||
static bool compare(const void *lhs, const void *rhs) ENTT_NOEXCEPT {
|
||||
return compare(0, *static_cast<const Type *>(lhs), *static_cast<const Type *>(rhs));
|
||||
}
|
||||
|
||||
@@ -331,9 +332,27 @@ class meta_any {
|
||||
template<typename Type>
|
||||
static void * copy_object(storage_type &storage, const void *instance) {
|
||||
using chunk_type = std::aligned_storage_t<sizeof(Type), alignof(Type)>;
|
||||
auto *chunk = new chunk_type;
|
||||
new (&storage) chunk_type *{chunk};
|
||||
return new (chunk) Type{*static_cast<const Type *>(instance)};
|
||||
auto chunk = std::make_unique<chunk_type>();
|
||||
new (&storage) chunk_type *{chunk.get()};
|
||||
auto *other = new (chunk.get()) Type{*static_cast<const Type *>(instance)};
|
||||
chunk.release();
|
||||
return other;
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
static void * steal_storage(storage_type &to, storage_type &from, destroy_fn_type *destroy_fn, void *) noexcept {
|
||||
void *instance = new (&to) Type{std::move(*reinterpret_cast<Type *>(&from))};
|
||||
destroy_fn(from);
|
||||
return instance;
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
static void * steal_object(storage_type &to, storage_type &from, destroy_fn_type *, void *instance) noexcept {
|
||||
using chunk_type = std::aligned_storage_t<sizeof(Type), alignof(Type)>;
|
||||
auto *chunk = *reinterpret_cast<chunk_type **>(&from);
|
||||
new (&to) chunk_type *{chunk};
|
||||
chunk->~chunk_type();
|
||||
return instance;
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
@@ -361,7 +380,8 @@ public:
|
||||
node{nullptr},
|
||||
destroy_fn{nullptr},
|
||||
compare_fn{nullptr},
|
||||
copy_fn{nullptr}
|
||||
copy_fn{nullptr},
|
||||
steal_fn{nullptr}
|
||||
{}
|
||||
|
||||
/**
|
||||
@@ -381,15 +401,18 @@ public:
|
||||
template<typename Type, typename... Args>
|
||||
meta_any(std::in_place_type_t<Type>, Args &&... args) {
|
||||
using actual_type = std::remove_cv_t<std::remove_reference_t<Type>>;
|
||||
constexpr auto sbo_allowed = sizeof(actual_type) <= sizeof(void *);
|
||||
node = internal::meta_info<Type>::resolve();
|
||||
|
||||
compare_fn = &compare<actual_type>;
|
||||
|
||||
constexpr auto sbo_allowed = sizeof(actual_type) <= sizeof(void *)
|
||||
&& std::is_nothrow_move_constructible_v<actual_type>;
|
||||
|
||||
if constexpr(sbo_allowed) {
|
||||
instance = new (&storage) actual_type{std::forward<Args>(args)...};
|
||||
destroy_fn = &destroy_storage<actual_type>;
|
||||
copy_fn = ©_storage<actual_type>;
|
||||
steal_fn = &steal_storage<actual_type>;
|
||||
} else {
|
||||
using chunk_type = std::aligned_storage_t<sizeof(actual_type), alignof(actual_type)>;
|
||||
|
||||
@@ -400,6 +423,7 @@ public:
|
||||
|
||||
destroy_fn = &destroy_object<actual_type>;
|
||||
copy_fn = ©_object<actual_type>;
|
||||
steal_fn = &steal_object<actual_type>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -434,6 +458,7 @@ public:
|
||||
destroy_fn = other.destroy_fn;
|
||||
compare_fn = other.compare_fn;
|
||||
copy_fn = other.copy_fn;
|
||||
steal_fn = other.steal_fn;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,7 +568,7 @@ public:
|
||||
* one otherwise.
|
||||
*/
|
||||
template<typename Type>
|
||||
meta_any convert() const ENTT_NOEXCEPT {
|
||||
meta_any convert() const {
|
||||
const auto *type = internal::meta_info<Type>::resolve();
|
||||
meta_any any{};
|
||||
|
||||
@@ -568,7 +593,7 @@ public:
|
||||
* @return True if the conversion is possible, false otherwise.
|
||||
*/
|
||||
template<typename Type>
|
||||
bool convert() ENTT_NOEXCEPT {
|
||||
bool convert() {
|
||||
bool valid = (node == internal::meta_info<Type>::resolve());
|
||||
|
||||
if(!valid) {
|
||||
@@ -601,7 +626,7 @@ public:
|
||||
* @return False if the container is empty, true otherwise.
|
||||
*/
|
||||
explicit operator bool() const ENTT_NOEXCEPT {
|
||||
return destroy_fn;
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -619,24 +644,19 @@ public:
|
||||
* @param lhs A valid meta any object.
|
||||
* @param rhs A valid meta any object.
|
||||
*/
|
||||
friend void swap(meta_any &lhs, meta_any &rhs) {
|
||||
friend void swap(meta_any &lhs, meta_any &rhs) ENTT_NOEXCEPT {
|
||||
using std::swap;
|
||||
|
||||
if(lhs && rhs) {
|
||||
storage_type buffer;
|
||||
void *tmp = lhs.copy_fn(buffer, lhs.instance);
|
||||
lhs.destroy_fn(lhs.storage);
|
||||
lhs.instance = rhs.copy_fn(lhs.storage, rhs.instance);
|
||||
rhs.destroy_fn(rhs.storage);
|
||||
rhs.instance = lhs.copy_fn(rhs.storage, tmp);
|
||||
lhs.destroy_fn(buffer);
|
||||
void *instance = lhs.steal_fn(buffer, lhs.storage, lhs.destroy_fn, lhs.instance);
|
||||
lhs.instance = rhs.steal_fn(lhs.storage, rhs.storage, rhs.destroy_fn, rhs.instance);
|
||||
rhs.instance = lhs.steal_fn(rhs.storage, buffer, lhs.destroy_fn, instance);
|
||||
} else if(lhs) {
|
||||
rhs.instance = lhs.copy_fn(rhs.storage, lhs.instance);
|
||||
lhs.destroy_fn(lhs.storage);
|
||||
rhs.instance = lhs.steal_fn(rhs.storage, lhs.storage, lhs.destroy_fn, lhs.instance);
|
||||
lhs.instance = nullptr;
|
||||
} else if(rhs) {
|
||||
lhs.instance = rhs.copy_fn(lhs.storage, rhs.instance);
|
||||
rhs.destroy_fn(rhs.storage);
|
||||
lhs.instance = rhs.steal_fn(lhs.storage, rhs.storage, rhs.destroy_fn, rhs.instance);
|
||||
rhs.instance = nullptr;
|
||||
}
|
||||
|
||||
@@ -644,15 +664,17 @@ public:
|
||||
std::swap(lhs.destroy_fn, rhs.destroy_fn);
|
||||
std::swap(lhs.compare_fn, rhs.compare_fn);
|
||||
std::swap(lhs.copy_fn, rhs.copy_fn);
|
||||
std::swap(lhs.steal_fn, rhs.steal_fn);
|
||||
}
|
||||
|
||||
private:
|
||||
storage_type storage;
|
||||
void *instance;
|
||||
internal::meta_type_node *node;
|
||||
destroy_fn_type destroy_fn;
|
||||
compare_fn_type compare_fn;
|
||||
copy_fn_type copy_fn;
|
||||
destroy_fn_type *destroy_fn;
|
||||
compare_fn_type *compare_fn;
|
||||
copy_fn_type *copy_fn;
|
||||
steal_fn_type *steal_fn;
|
||||
};
|
||||
|
||||
|
||||
@@ -2071,7 +2093,7 @@ struct meta_function_helper<Ret(Args...)> {
|
||||
|
||||
static constexpr auto size = sizeof...(Args);
|
||||
|
||||
static auto arg(typename internal::meta_func_node::size_type index) {
|
||||
static auto arg(typename internal::meta_func_node::size_type index) ENTT_NOEXCEPT {
|
||||
return std::array<meta_type_node *, sizeof...(Args)>{{meta_info<Args>::resolve()...}}[index];
|
||||
}
|
||||
};
|
||||
@@ -2283,11 +2305,11 @@ inline meta_type_node * meta_node<Type>::resolve() ENTT_NOEXCEPT {
|
||||
std::is_member_object_pointer_v<Type>,
|
||||
std::is_member_function_pointer_v<Type>,
|
||||
std::extent_v<Type>,
|
||||
[]() -> meta_type {
|
||||
[]() ENTT_NOEXCEPT -> meta_type {
|
||||
return internal::meta_info<std::remove_pointer_t<Type>>::resolve();
|
||||
},
|
||||
&destroy<Type>,
|
||||
[]() -> meta_type {
|
||||
[]() ENTT_NOEXCEPT -> meta_type {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
@@ -424,6 +425,28 @@ TEST_F(Meta, MetaAnyNoSBOMoveAssignment) {
|
||||
ASSERT_NE(other, fat_type{});
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaAnySBOMoveInvalidate) {
|
||||
entt::meta_any any{42};
|
||||
entt::meta_any other{std::move(any)};
|
||||
entt::meta_any valid = std::move(other);
|
||||
|
||||
ASSERT_FALSE(any);
|
||||
ASSERT_FALSE(other);
|
||||
ASSERT_TRUE(valid);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaAnyNoSBOMoveInvalidate) {
|
||||
int value = 42;
|
||||
fat_type instance{&value};
|
||||
entt::meta_any any{instance};
|
||||
entt::meta_any other{std::move(any)};
|
||||
entt::meta_any valid = std::move(other);
|
||||
|
||||
ASSERT_FALSE(any);
|
||||
ASSERT_FALSE(other);
|
||||
ASSERT_TRUE(valid);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaAnySBODestruction) {
|
||||
ASSERT_EQ(empty_type::counter, 0);
|
||||
{ entt::meta_any any{empty_type{}}; }
|
||||
|
||||
Reference in New Issue
Block a user