Browse Source

LValue handling of the scope guard move ctor implemented (fixes #41).

main
offa 7 years ago
parent
commit
5e610e63e4
2 changed files with 42 additions and 3 deletions
  1. +8
    -3
      include/scope_guard.h
  2. +34
    -0
      test/ScopeGuardTest.cpp

+ 8
- 3
include/scope_guard.h View File

std::enable_if_t<std::is_constructible<Deleter, D>::value, int> = 0, std::enable_if_t<std::is_constructible<Deleter, D>::value, int> = 0,
std::enable_if_t<std::is_lvalue_reference<D>::value, int> = 0 std::enable_if_t<std::is_lvalue_reference<D>::value, int> = 0
> >
explicit scope_guard_t(D&& deleter) : m_deleter(deleter),
explicit scope_guard_t(D&& deleter) try : m_deleter(deleter),
m_execute_on_destruction(true) m_execute_on_destruction(true)
{ {
} }
catch( ... )
{
deleter();
throw;
}




scope_guard_t(const scope_guard_t&) = delete; scope_guard_t(const scope_guard_t&) = delete;




template<class Deleter> template<class Deleter>
scope_guard_t<Deleter> scope_guard(Deleter&& deleter) noexcept
scope_guard_t<std::decay_t<Deleter>> scope_guard(Deleter&& deleter) noexcept
{ {
return scope_guard_t<Deleter>{std::move(deleter)};
return scope_guard_t<std::decay_t<Deleter>>{std::forward<Deleter>(deleter)};
} }


} }

+ 34
- 0
test/ScopeGuardTest.cpp View File

MAKE_MOCK0(deleter, void()); MAKE_MOCK0(deleter, void());
}; };



struct ThrowOnCopyMock
{
ThrowOnCopyMock() = default;

ThrowOnCopyMock(const ThrowOnCopyMock&)
{
throw std::exception{};
}

MAKE_CONST_MOCK0(deleter, void());

void operator()() const
{
this->deleter();
}

ThrowOnCopyMock& operator=(const ThrowOnCopyMock&)
{
throw std::exception{};
}
};

CallMock m; CallMock m;



void deleter() void deleter()
{ {
m.deleter(); m.deleter();
static_cast<void>(guard); static_cast<void>(guard);
} }


TEST_CASE("deleter called and rethrow on copy exception", "[ScopeGuard]")
{
REQUIRE_THROWS([] {
const ThrowOnCopyMock noMove;
REQUIRE_CALL(noMove, deleter());

sr::scope_guard_t<decltype(noMove)> guard{noMove};
}());
}

TEST_CASE("deleter is not called if released", "[ScopeGuard]") TEST_CASE("deleter is not called if released", "[ScopeGuard]")
{ {
REQUIRE_CALL(m, deleter()).TIMES(0); REQUIRE_CALL(m, deleter()).TIMES(0);

Loading…
Cancel
Save