&& std::is_nothrow_move_constructible_v<D>) | && std::is_nothrow_move_constructible_v<D>) | ||||
: resource(std::move_if_noexcept(other.resource.get()), scope_exit{[] { }}), | : resource(std::move_if_noexcept(other.resource.get()), scope_exit{[] { }}), | ||||
deleter(std::move_if_noexcept(other.deleter.get()), scope_exit{[&other] { | deleter(std::move_if_noexcept(other.deleter.get()), scope_exit{[&other] { | ||||
other.get_deleter()(other.resource.get()); | |||||
if( other.execute_on_reset == true ) | |||||
{ | |||||
other.get_deleter()(other.resource.get()); | |||||
} | |||||
other.release(); }}), | other.release(); }}), | ||||
execute_on_reset(std::exchange(other.execute_on_reset, false)) | execute_on_reset(std::exchange(other.execute_on_reset, false)) | ||||
{ | { |
CopyMock(const CopyMock&) { } | CopyMock(const CopyMock&) { } | ||||
}; | }; | ||||
struct ConditionalThrowOnCopyDeleter | |||||
{ | |||||
ConditionalThrowOnCopyDeleter() { } | |||||
ConditionalThrowOnCopyDeleter(const ConditionalThrowOnCopyDeleter&) | |||||
{ | |||||
if( throwOnNextCopy == true ) | |||||
{ | |||||
throw std::exception{}; | |||||
} | |||||
throwOnNextCopy = false; | |||||
} | |||||
MAKE_CONST_MOCK1(deleter, void(Handle)); | |||||
void operator()(Handle h) const | |||||
{ | |||||
this->deleter(h); | |||||
} | |||||
static inline bool throwOnNextCopy{false}; | |||||
}; | |||||
} | } | ||||
[[maybe_unused]] auto guard = std::move(movedFrom); | [[maybe_unused]] auto guard = std::move(movedFrom); | ||||
} | } | ||||
TEST_CASE("move-construction prevents double release", "[UniqueResource]") | |||||
{ | |||||
auto movedFrom = sr::unique_resource{Handle{3}, ConditionalThrowOnCopyDeleter{}}; | |||||
movedFrom.release(); | |||||
ConditionalThrowOnCopyDeleter::throwOnNextCopy = true; | |||||
REQUIRE_THROWS([&movedFrom] { [[maybe_unused]] auto guard = std::move(movedFrom); }()); | |||||
} | |||||
TEST_CASE("move assignment calls deleter", "[UniqueResource]") | TEST_CASE("move assignment calls deleter", "[UniqueResource]") | ||||
{ | { | ||||
auto moveFrom = sr::unique_resource{Handle{3}, deleter}; | auto moveFrom = sr::unique_resource{Handle{3}, deleter}; |