mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-14 03:29:28 +07:00
value's exception safety fixes
This commit is contained in:
@@ -9507,7 +9507,7 @@ namespace meta_hpp
|
||||
}
|
||||
}
|
||||
|
||||
static void do_copy(const uvalue& self, uvalue& to) noexcept {
|
||||
static void do_copy(const uvalue& self, uvalue& to) {
|
||||
META_HPP_DEV_ASSERT(!to);
|
||||
|
||||
auto&& [tag, vtable] = unpack_vtag(self);
|
||||
@@ -9548,15 +9548,21 @@ namespace meta_hpp
|
||||
|
||||
if ( l && r ) {
|
||||
if ( unpack_vtag(l).first == storage_e::external ) {
|
||||
r = std::exchange(l, std::move(r));
|
||||
uvalue o;
|
||||
do_move(std::move(l), o);
|
||||
do_move(std::move(r), l);
|
||||
do_move(std::move(o), r);
|
||||
} else {
|
||||
l = std::exchange(r, std::move(l));
|
||||
uvalue o;
|
||||
do_move(std::move(r), o);
|
||||
do_move(std::move(l), r);
|
||||
do_move(std::move(o), l);
|
||||
}
|
||||
} else {
|
||||
if ( l ) {
|
||||
r = std::move(l);
|
||||
do_move(std::move(l), r);
|
||||
} else {
|
||||
l = std::move(r);
|
||||
do_move(std::move(r), l);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9667,16 +9673,14 @@ namespace meta_hpp
|
||||
|
||||
inline uvalue& uvalue::operator=(uvalue&& other) noexcept {
|
||||
if ( this != &other ) {
|
||||
vtable_t::do_reset(*this);
|
||||
vtable_t::do_move(std::move(other), *this);
|
||||
uvalue{std::move(other)}.swap(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uvalue& uvalue::operator=(const uvalue& other) {
|
||||
if ( this != &other ) {
|
||||
vtable_t::do_reset(*this);
|
||||
vtable_t::do_copy(other, *this);
|
||||
uvalue{other}.swap(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -9688,8 +9692,7 @@ namespace meta_hpp
|
||||
|
||||
template < typename T, typename Tp, typename >
|
||||
uvalue& uvalue::operator=(T&& val) {
|
||||
vtable_t::do_reset(*this);
|
||||
vtable_t::do_ctor<T>(*this, std::forward<T>(val));
|
||||
uvalue{std::forward<T>(val)}.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
68
develop/untests/meta_issues/random_issue_4.cpp
Normal file
68
develop/untests/meta_issues/random_issue_4.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
/*******************************************************************************
|
||||
* This file is part of the "https://github.com/blackmatov/meta.hpp"
|
||||
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||
* Copyright (C) 2021-2023, by Matvey Cherevko (blackmatov@gmail.com)
|
||||
******************************************************************************/
|
||||
|
||||
#include <meta.hpp/meta_all.hpp>
|
||||
#include <doctest/doctest.h>
|
||||
|
||||
#if !defined(META_HPP_NO_EXCEPTIONS)
|
||||
|
||||
namespace
|
||||
{
|
||||
struct throw_on_copy {
|
||||
throw_on_copy() = default;
|
||||
|
||||
[[noreturn]] throw_on_copy(const throw_on_copy&) {
|
||||
throw 42;
|
||||
}
|
||||
};
|
||||
|
||||
struct throw_on_move {
|
||||
throw_on_move() = default;
|
||||
|
||||
[[noreturn]] throw_on_move(throw_on_move&&) {
|
||||
throw 42;
|
||||
}
|
||||
|
||||
[[noreturn]] throw_on_move(const throw_on_move&) {
|
||||
throw 42;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_issues/random/4") {
|
||||
namespace meta = meta_hpp;
|
||||
|
||||
meta::uvalue v{42};
|
||||
CHECK(v.get_type() == meta::resolve_type<int>());
|
||||
|
||||
SUBCASE("1") {
|
||||
CHECK_THROWS(v = throw_on_copy{});
|
||||
CHECK(v.get_type() == meta::resolve_type<int>());
|
||||
}
|
||||
|
||||
SUBCASE("2") {
|
||||
CHECK_THROWS(v = throw_on_move{});
|
||||
CHECK(v.get_type() == meta::resolve_type<int>());
|
||||
}
|
||||
|
||||
SUBCASE("3") {
|
||||
meta::uvalue v2{std::in_place_type<throw_on_copy>};
|
||||
CHECK_THROWS(v = v2);
|
||||
CHECK(v.get_type() == meta::resolve_type<int>());
|
||||
CHECK_NOTHROW(v = std::move(v2));
|
||||
CHECK(v.get_type() == meta::resolve_type<throw_on_copy>());
|
||||
}
|
||||
|
||||
SUBCASE("4") {
|
||||
meta::uvalue v2{std::in_place_type<throw_on_move>};
|
||||
CHECK_THROWS(v = v2);
|
||||
CHECK(v.get_type() == meta::resolve_type<int>());
|
||||
CHECK_NOTHROW(v = std::move(v2));
|
||||
CHECK(v.get_type() == meta::resolve_type<throw_on_move>());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -381,7 +381,7 @@ TEST_CASE("meta/meta_utilities/value") {
|
||||
|
||||
val_dst = std::move(val_src2);
|
||||
CHECK(val_dst.as<ivec2>() == ivec2{1,2});
|
||||
CHECK(ivec2::move_constructor_counter == 2);
|
||||
CHECK(ivec2::move_constructor_counter == 3);
|
||||
CHECK(ivec2::copy_constructor_counter == 0);
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ TEST_CASE("meta/meta_utilities/value") {
|
||||
|
||||
val_dst = val_src2;
|
||||
CHECK(val_dst.as<ivec2>() == ivec2{1,2});
|
||||
CHECK(ivec2::move_constructor_counter == 1);
|
||||
CHECK(ivec2::move_constructor_counter == 2);
|
||||
CHECK(ivec2::copy_constructor_counter == 1);
|
||||
|
||||
CHECK(val_src2.as<ivec2>() == ivec2{1,2});
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace meta_hpp
|
||||
}
|
||||
}
|
||||
|
||||
static void do_copy(const uvalue& self, uvalue& to) noexcept {
|
||||
static void do_copy(const uvalue& self, uvalue& to) {
|
||||
META_HPP_DEV_ASSERT(!to);
|
||||
|
||||
auto&& [tag, vtable] = unpack_vtag(self);
|
||||
@@ -152,15 +152,21 @@ namespace meta_hpp
|
||||
|
||||
if ( l && r ) {
|
||||
if ( unpack_vtag(l).first == storage_e::external ) {
|
||||
r = std::exchange(l, std::move(r));
|
||||
uvalue o;
|
||||
do_move(std::move(l), o);
|
||||
do_move(std::move(r), l);
|
||||
do_move(std::move(o), r);
|
||||
} else {
|
||||
l = std::exchange(r, std::move(l));
|
||||
uvalue o;
|
||||
do_move(std::move(r), o);
|
||||
do_move(std::move(l), r);
|
||||
do_move(std::move(o), l);
|
||||
}
|
||||
} else {
|
||||
if ( l ) {
|
||||
r = std::move(l);
|
||||
do_move(std::move(l), r);
|
||||
} else {
|
||||
l = std::move(r);
|
||||
do_move(std::move(r), l);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -271,16 +277,14 @@ namespace meta_hpp
|
||||
|
||||
inline uvalue& uvalue::operator=(uvalue&& other) noexcept {
|
||||
if ( this != &other ) {
|
||||
vtable_t::do_reset(*this);
|
||||
vtable_t::do_move(std::move(other), *this);
|
||||
uvalue{std::move(other)}.swap(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline uvalue& uvalue::operator=(const uvalue& other) {
|
||||
if ( this != &other ) {
|
||||
vtable_t::do_reset(*this);
|
||||
vtable_t::do_copy(other, *this);
|
||||
uvalue{other}.swap(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -292,8 +296,7 @@ namespace meta_hpp
|
||||
|
||||
template < typename T, typename Tp, typename >
|
||||
uvalue& uvalue::operator=(T&& val) {
|
||||
vtable_t::do_reset(*this);
|
||||
vtable_t::do_ctor<T>(*this, std::forward<T>(val));
|
||||
uvalue{std::forward<T>(val)}.swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user