meta: overall improvements

This commit is contained in:
Michele Caini
2019-06-10 23:19:19 +02:00
parent 8d08ffc4ae
commit 43932492a7
3 changed files with 106 additions and 61 deletions

View File

@@ -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;
}
};

View File

@@ -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 = &copy_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 = &copy_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;
}
};

View File

@@ -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{}}; }