@@ -50,7 +50,7 @@ namespace sr::detail | |||
void reset(T&& newValue) noexcept(std::is_nothrow_assignable_v<T, decltype(std::move_if_noexcept(newValue))>) | |||
{ | |||
m_value = std::move_if_noexcept(newValue); | |||
m_value = std::forward<T>(newValue); | |||
} | |||
void reset(const T& newValue) noexcept(std::is_nothrow_assignable_v<T, const T&>) |
@@ -100,9 +100,20 @@ namespace sr | |||
template<class RR> | |||
void reset(RR&& r) | |||
{ | |||
auto se = scope_exit{[this, &r] { get_deleter()(r); }}; | |||
reset(); | |||
m_resource.reset(std::forward<RR>(r)); | |||
using R1 = typename detail::Wrapper<R>::type; | |||
auto se = scope_exit{[this, &r] { get_deleter()(r); }}; | |||
if constexpr( std::is_nothrow_assignable_v<R1&, RR> == true ) | |||
{ | |||
m_resource.reset(std::forward<RR>(r)); | |||
} | |||
else | |||
{ | |||
m_resource = std::as_const(r); | |||
} | |||
m_execute_on_destruction = true; | |||
se.release(); | |||
} |
@@ -120,7 +120,7 @@ TEST_CASE("reset does not call deleter if released", "[UniqueResource]") | |||
guard.reset(); | |||
} | |||
TEST_CASE("reset sets new value and calls deleter on previous", "[UniqueResource]") | |||
TEST_CASE("reset sets new rvalue and calls deleter on previous", "[UniqueResource]") | |||
{ | |||
REQUIRE_CALL(m, deleter(3)); | |||
REQUIRE_CALL(m, deleter(7)); | |||
@@ -128,6 +128,15 @@ TEST_CASE("reset sets new value and calls deleter on previous", "[UniqueResource | |||
guard.reset(Handle{7}); | |||
} | |||
TEST_CASE("reset sets new lvalue and calls deleter on previous", "[UniqueResource]") | |||
{ | |||
REQUIRE_CALL(m, deleter(3)); | |||
REQUIRE_CALL(m, deleter(7)); | |||
auto guard = sr::unique_resource{Handle{3}, deleter}; | |||
const Handle h{7}; | |||
guard.reset(h); | |||
} | |||
TEST_CASE("reset handles exception on assignment", "[UniqueResource]") | |||
{ | |||
REQUIRE_CALL(m, deleter(3)); |