meta_any: fixed #180

This commit is contained in:
Michele Caini
2019-02-01 23:48:00 +01:00
parent 8b360479f4
commit 45fdab27c9
2 changed files with 55 additions and 23 deletions

View File

@@ -379,9 +379,7 @@ public:
compare_fn = &compare<actual_type>;
if constexpr(sizeof(actual_type) <= sizeof(void *)) {
new (&storage) actual_type{std::forward<Type>(type)};
instance = &storage;
instance = new (&storage) actual_type{std::forward<Type>(type)};
destroy_fn = &destroy_storage<actual_type>;
copy_fn = &copy_storage<actual_type>;
} else {
@@ -440,7 +438,7 @@ public:
* @return This meta any object.
*/
meta_any & operator=(meta_any other) {
swap(*this, other);
swap(other, *this);
return *this;
}
@@ -550,7 +548,7 @@ public:
auto any = std::as_const(*this).convert<Type>();
if(any) {
std::swap(*this, any);
std::swap(any, *this);
valid = true;
}
}
@@ -584,20 +582,28 @@ public:
friend void swap(meta_any &lhs, meta_any &rhs) {
using std::swap;
std::swap(lhs.storage, rhs.storage);
std::swap(lhs.instance, rhs.instance);
std::swap(lhs.destroy_fn, rhs.destroy_fn);
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);
} else if(lhs) {
rhs.instance = lhs.copy_fn(rhs.storage, lhs.instance);
lhs.destroy_fn(lhs.storage);
lhs.instance = nullptr;
} else if(rhs) {
lhs.instance = rhs.copy_fn(lhs.storage, rhs.instance);
rhs.destroy_fn(rhs.storage);
rhs.instance = nullptr;
}
std::swap(lhs.node, rhs.node);
std::swap(lhs.destroy_fn, rhs.destroy_fn);
std::swap(lhs.compare_fn, rhs.compare_fn);
std::swap(lhs.copy_fn, rhs.copy_fn);
if(lhs.instance == &rhs.storage) {
lhs.instance = &lhs.storage;
}
if(rhs.instance == &lhs.storage) {
rhs.instance = &rhs.storage;
}
}
private:

View File

@@ -367,15 +367,13 @@ TEST_F(Meta, MetaAnyNoSBOMoveAssignment) {
TEST_F(Meta, MetaAnySBODestruction) {
ASSERT_EQ(empty_type::counter, 0);
entt::meta_any any{empty_type{}};
any = {};
{ entt::meta_any any{empty_type{}}; }
ASSERT_EQ(empty_type::counter, 1);
}
TEST_F(Meta, MetaAnyNoSBODestruction) {
ASSERT_EQ(fat_type::counter, 0);
entt::meta_any any{fat_type{}};
any = {};
{ entt::meta_any any{fat_type{}}; }
ASSERT_EQ(fat_type::counter, 1);
}
@@ -416,6 +414,37 @@ TEST_F(Meta, MetaAnySBOWithNoSBOSwap) {
ASSERT_EQ(rhs.cast<fat_type>().bar, &value);
}
TEST_F(Meta, MetaAnySBOWithEmptySwap) {
entt::meta_any lhs{'c'};
entt::meta_any rhs{};
std::swap(lhs, rhs);
ASSERT_FALSE(lhs);
ASSERT_TRUE(rhs.can_cast<char>());
ASSERT_EQ(rhs.cast<char>(), 'c');
std::swap(lhs, rhs);
ASSERT_FALSE(rhs);
ASSERT_TRUE(lhs.can_cast<char>());
ASSERT_EQ(lhs.cast<char>(), 'c');
}
TEST_F(Meta, MetaAnyNoSBOWithEmptySwap) {
int i;
entt::meta_any lhs{fat_type{&i}};
entt::meta_any rhs{};
std::swap(lhs, rhs);
ASSERT_EQ(rhs.cast<fat_type>().bar, &i);
std::swap(lhs, rhs);
ASSERT_EQ(lhs.cast<fat_type>().bar, &i);
}
TEST_F(Meta, MetaAnyComparable) {
entt::meta_any any{'c'};
@@ -1283,14 +1312,12 @@ TEST_F(Meta, MetaTypeConstructMetaAnyArgs) {
ASSERT_EQ(any.cast<derived_type>().c, 'c');
}
TEST_F(Meta, MetaTypeConstructInvalidArgs) {
auto type = entt::resolve<derived_type>();
auto any = type.construct(entt::meta_any{base_type{}}, entt::meta_any{'c'}, entt::meta_any{42});
ASSERT_FALSE(any);
}
TEST_F(Meta, MetaTypeConstructCastAndConvert) {
auto type = entt::resolve<derived_type>();
auto any = type.construct(entt::meta_any{derived_type{}}, entt::meta_any{42.}, entt::meta_any{'c'});
@@ -1301,7 +1328,6 @@ TEST_F(Meta, MetaTypeConstructCastAndConvert) {
ASSERT_EQ(any.cast<derived_type>().c, 'c');
}
TEST_F(Meta, MetaTypeDestroyDtor) {
auto type = entt::resolve<empty_type>();