mirror of
https://github.com/BlackMATov/meta.hpp.git
synced 2025-12-13 19:18:01 +07:00
insert_or_assign exception workarounds
This commit is contained in:
@@ -386,7 +386,7 @@ namespace meta_hpp::detail
|
||||
: std::logic_error(ec.message())
|
||||
, error_code_{ec} {}
|
||||
|
||||
[[nodiscard]] const std::error_code& code() const noexcept {
|
||||
[[nodiscard]] const std::error_code& get_code() const noexcept {
|
||||
return error_code_;
|
||||
}
|
||||
|
||||
@@ -756,6 +756,7 @@ namespace std
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < typename Key, typename Compare, typename Allocator >
|
||||
requires std::is_move_constructible_v<Key> && std::is_move_assignable_v<Key>
|
||||
typename std::set<Key, Compare, Allocator>::iterator insert_or_assign( //
|
||||
std::set<Key, Compare, Allocator>& set,
|
||||
typename std::set<Key, Compare, Allocator>::value_type&& value
|
||||
@@ -767,11 +768,20 @@ namespace meta_hpp::detail
|
||||
}
|
||||
|
||||
auto node = set.extract(position++);
|
||||
node.value() = std::move(value);
|
||||
|
||||
META_HPP_TRY {
|
||||
node.value() = std::move(value);
|
||||
}
|
||||
META_HPP_CATCH(...) {
|
||||
set.insert(position, std::move(node));
|
||||
META_HPP_RETHROW();
|
||||
}
|
||||
|
||||
return set.insert(position, std::move(node));
|
||||
}
|
||||
|
||||
template < typename Key, typename Compare, typename Allocator >
|
||||
requires std::is_copy_constructible_v<Key> && std::is_copy_assignable_v<Key>
|
||||
typename std::set<Key, Compare, Allocator>::iterator insert_or_assign( //
|
||||
std::set<Key, Compare, Allocator>& set,
|
||||
const typename std::set<Key, Compare, Allocator>::value_type& value
|
||||
@@ -783,7 +793,15 @@ namespace meta_hpp::detail
|
||||
}
|
||||
|
||||
auto node = set.extract(position++);
|
||||
node.value() = value;
|
||||
|
||||
META_HPP_TRY {
|
||||
node.value() = value;
|
||||
}
|
||||
META_HPP_CATCH(...) {
|
||||
set.insert(position, std::move(node));
|
||||
META_HPP_RETHROW();
|
||||
}
|
||||
|
||||
return set.insert(position, std::move(node));
|
||||
}
|
||||
}
|
||||
@@ -2877,7 +2895,7 @@ namespace meta_hpp
|
||||
class uvalue final {
|
||||
public:
|
||||
uvalue() = default;
|
||||
~uvalue();
|
||||
~uvalue() noexcept;
|
||||
|
||||
uvalue(uvalue&& other) noexcept;
|
||||
uvalue(const uvalue& other);
|
||||
@@ -2921,7 +2939,7 @@ namespace meta_hpp
|
||||
[[nodiscard]] bool is_valid() const noexcept;
|
||||
[[nodiscard]] explicit operator bool() const noexcept;
|
||||
|
||||
void reset();
|
||||
void reset() noexcept;
|
||||
void swap(uvalue& other) noexcept;
|
||||
|
||||
[[nodiscard]] any_type get_type() const noexcept;
|
||||
@@ -8553,7 +8571,7 @@ namespace meta_hpp
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline uvalue::~uvalue() {
|
||||
inline uvalue::~uvalue() noexcept {
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -8638,7 +8656,7 @@ namespace meta_hpp
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline void uvalue::reset() {
|
||||
inline void uvalue::reset() noexcept {
|
||||
vtable_t::do_reset(*this);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,114 @@ namespace
|
||||
return l.key == r.key && l.data == r.data;
|
||||
}
|
||||
};
|
||||
|
||||
struct exception_on_move_value {
|
||||
int key{};
|
||||
int data{};
|
||||
|
||||
exception_on_move_value(int k, int d)
|
||||
: key{k}
|
||||
, data{d} {}
|
||||
|
||||
exception_on_move_value(const exception_on_move_value&) = default;
|
||||
exception_on_move_value& operator=(const exception_on_move_value&) = default;
|
||||
|
||||
exception_on_move_value(exception_on_move_value&& other)
|
||||
: key{other.key}
|
||||
, data{other.data} {
|
||||
if ( other.data != 42 ) {
|
||||
other.key = 0;
|
||||
other.data = 0;
|
||||
return;
|
||||
}
|
||||
#if !defined(META_HPP_NO_EXCEPTIONS)
|
||||
throw std::exception{};
|
||||
#else
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
exception_on_move_value& operator=(exception_on_move_value&& other) {
|
||||
if ( this == &other ) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
if ( other.data != 42 ) {
|
||||
key = other.key;
|
||||
data = other.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(META_HPP_NO_EXCEPTIONS)
|
||||
throw std::exception{};
|
||||
#else
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
friend bool operator<(const exception_on_move_value& l, const exception_on_move_value& r) noexcept {
|
||||
return l.key < r.key;
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
friend bool operator==(const exception_on_move_value& l, const exception_on_move_value& r) noexcept {
|
||||
return l.key == r.key && l.data == r.data;
|
||||
}
|
||||
};
|
||||
|
||||
struct exception_on_copy_value {
|
||||
int key{};
|
||||
int data{};
|
||||
|
||||
exception_on_copy_value(int k, int d)
|
||||
: key{k}
|
||||
, data{d} {}
|
||||
|
||||
exception_on_copy_value(exception_on_copy_value&& other) = default;
|
||||
exception_on_copy_value& operator=(exception_on_copy_value&& other) = default;
|
||||
|
||||
exception_on_copy_value(const exception_on_copy_value& other)
|
||||
: key{other.key}
|
||||
, data{other.data} {
|
||||
if ( other.data != 42 ) {
|
||||
return;
|
||||
}
|
||||
#if !defined(META_HPP_NO_EXCEPTIONS)
|
||||
throw std::exception{};
|
||||
#else
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
exception_on_copy_value& operator=(const exception_on_copy_value& other) {
|
||||
if ( this == &other ) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
if ( other.data != 42 ) {
|
||||
key = other.key;
|
||||
data = other.data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if !defined(META_HPP_NO_EXCEPTIONS)
|
||||
throw std::exception{};
|
||||
#else
|
||||
std::abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
friend bool operator<(const exception_on_copy_value& l, const exception_on_copy_value& r) noexcept {
|
||||
return l.key < r.key;
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
friend bool operator==(const exception_on_copy_value& l, const exception_on_copy_value& r) noexcept {
|
||||
return l.key == r.key && l.data == r.data;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_base/insert_or_assign") {
|
||||
@@ -105,3 +213,34 @@ TEST_CASE("meta/meta_base/insert_or_assign") {
|
||||
CHECK(s == std::set<copyable_value, std::less<>>{{1, 10}, {3, 42}});
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("meta/meta_base/insert_or_assign/exceptions") {
|
||||
namespace meta = meta_hpp;
|
||||
using meta::detail::insert_or_assign;
|
||||
|
||||
SUBCASE("on_move/insert") {
|
||||
std::set<exception_on_move_value, std::less<>> s{{1, 10}, {3, 30}};
|
||||
CHECK_THROWS(insert_or_assign(s, exception_on_move_value{2, 42}));
|
||||
CHECK(s == std::set<exception_on_move_value, std::less<>>{{1, 10}, {3, 30}});
|
||||
}
|
||||
|
||||
SUBCASE("on_move/replace") {
|
||||
std::set<exception_on_move_value, std::less<>> s{{1, 10}, {3, 30}};
|
||||
CHECK_THROWS(insert_or_assign(s, exception_on_move_value{3, 42}));
|
||||
CHECK(s == std::set<exception_on_move_value, std::less<>>{{1, 10}, {3, 30}});
|
||||
}
|
||||
|
||||
SUBCASE("on_copy/insert") {
|
||||
std::set<exception_on_copy_value, std::less<>> s{{1, 10}, {3, 30}};
|
||||
exception_on_copy_value v{2, 42};
|
||||
CHECK_THROWS(insert_or_assign(s, v));
|
||||
CHECK(s == std::set<exception_on_copy_value, std::less<>>{{1, 10}, {3, 30}});
|
||||
}
|
||||
|
||||
SUBCASE("on_copy/replace") {
|
||||
std::set<exception_on_copy_value, std::less<>> s{{1, 10}, {3, 30}};
|
||||
exception_on_copy_value v{3, 42};
|
||||
CHECK_THROWS(insert_or_assign(s, v));
|
||||
CHECK(s == std::set<exception_on_copy_value, std::less<>>{{1, 10}, {3, 30}});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace meta_hpp::detail
|
||||
: std::logic_error(ec.message())
|
||||
, error_code_{ec} {}
|
||||
|
||||
[[nodiscard]] const std::error_code& code() const noexcept {
|
||||
[[nodiscard]] const std::error_code& get_code() const noexcept {
|
||||
return error_code_;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "base.hpp"
|
||||
#include "exceptions.hpp"
|
||||
|
||||
namespace meta_hpp::detail
|
||||
{
|
||||
template < typename Key, typename Compare, typename Allocator >
|
||||
requires std::is_move_constructible_v<Key> && std::is_move_assignable_v<Key>
|
||||
typename std::set<Key, Compare, Allocator>::iterator insert_or_assign( //
|
||||
std::set<Key, Compare, Allocator>& set,
|
||||
typename std::set<Key, Compare, Allocator>::value_type&& value
|
||||
@@ -22,11 +24,20 @@ namespace meta_hpp::detail
|
||||
}
|
||||
|
||||
auto node = set.extract(position++);
|
||||
node.value() = std::move(value);
|
||||
|
||||
META_HPP_TRY {
|
||||
node.value() = std::move(value);
|
||||
}
|
||||
META_HPP_CATCH(...) {
|
||||
set.insert(position, std::move(node));
|
||||
META_HPP_RETHROW();
|
||||
}
|
||||
|
||||
return set.insert(position, std::move(node));
|
||||
}
|
||||
|
||||
template < typename Key, typename Compare, typename Allocator >
|
||||
requires std::is_copy_constructible_v<Key> && std::is_copy_assignable_v<Key>
|
||||
typename std::set<Key, Compare, Allocator>::iterator insert_or_assign( //
|
||||
std::set<Key, Compare, Allocator>& set,
|
||||
const typename std::set<Key, Compare, Allocator>::value_type& value
|
||||
@@ -38,7 +49,15 @@ namespace meta_hpp::detail
|
||||
}
|
||||
|
||||
auto node = set.extract(position++);
|
||||
node.value() = value;
|
||||
|
||||
META_HPP_TRY {
|
||||
node.value() = value;
|
||||
}
|
||||
META_HPP_CATCH(...) {
|
||||
set.insert(position, std::move(node));
|
||||
META_HPP_RETHROW();
|
||||
}
|
||||
|
||||
return set.insert(position, std::move(node));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace meta_hpp
|
||||
class uvalue final {
|
||||
public:
|
||||
uvalue() = default;
|
||||
~uvalue();
|
||||
~uvalue() noexcept;
|
||||
|
||||
uvalue(uvalue&& other) noexcept;
|
||||
uvalue(const uvalue& other);
|
||||
@@ -73,7 +73,7 @@ namespace meta_hpp
|
||||
[[nodiscard]] bool is_valid() const noexcept;
|
||||
[[nodiscard]] explicit operator bool() const noexcept;
|
||||
|
||||
void reset();
|
||||
void reset() noexcept;
|
||||
void swap(uvalue& other) noexcept;
|
||||
|
||||
[[nodiscard]] any_type get_type() const noexcept;
|
||||
|
||||
@@ -254,7 +254,7 @@ namespace meta_hpp
|
||||
|
||||
namespace meta_hpp
|
||||
{
|
||||
inline uvalue::~uvalue() {
|
||||
inline uvalue::~uvalue() noexcept {
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ namespace meta_hpp
|
||||
return is_valid();
|
||||
}
|
||||
|
||||
inline void uvalue::reset() {
|
||||
inline void uvalue::reset() noexcept {
|
||||
vtable_t::do_reset(*this);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user