Fix finally with mutable lvalue invokable

This commit is contained in:
Pascal Menuet 2020-08-14 16:11:11 +02:00
parent 06c46195ee
commit c25a7544b8
2 changed files with 26 additions and 8 deletions

View File

@ -52,6 +52,8 @@ template <class F>
class final_action class final_action
{ {
public: public:
static_assert(!std::is_reference<F>::value && !std::is_const<F>::value && !std::is_volatile<F>::value, "Final_action should store its callable by value");
explicit final_action(F f) noexcept : f_(std::move(f)) {} explicit final_action(F f) noexcept : f_(std::move(f)) {}
final_action(final_action&& other) noexcept : f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false)) {} final_action(final_action&& other) noexcept : f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false)) {}
@ -73,15 +75,9 @@ private:
// finally() - convenience function to generate a final_action // finally() - convenience function to generate a final_action
template <class F> template <class F>
GSL_NODISCARD final_action<F> finally(const F& f) noexcept GSL_NODISCARD final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type> finally(F&& f) noexcept
{ {
return final_action<F>(f); return final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>(std::forward<F>(f));
}
template <class F>
GSL_NODISCARD final_action<F> finally(F&& f) noexcept
{
return final_action<F>(std::forward<F>(f));
} }
// narrow_cast(): a searchable way to do narrowing casts of values // narrow_cast(): a searchable way to do narrowing casts of values

View File

@ -70,6 +70,28 @@ TEST(utils_tests, finally_lambda_move)
EXPECT_TRUE(i == 1); EXPECT_TRUE(i == 1);
} }
TEST(utils_tests, finally_const_lvalue_lambda)
{
int i = 0;
{
const auto const_lvalue_lambda = [&]() { f(i); };
auto _ = finally(const_lvalue_lambda);
EXPECT_TRUE(i == 0);
}
EXPECT_TRUE(i == 1);
}
TEST(utils_tests, finally_mutable_lvalue_lambda)
{
int i = 0;
{
auto mutable_lvalue_lambda = [&]() { f(i); };
auto _ = finally(mutable_lvalue_lambda);
EXPECT_TRUE(i == 0);
}
EXPECT_TRUE(i == 1);
}
TEST(utils_tests, finally_function_with_bind) TEST(utils_tests, finally_function_with_bind)
{ {
int i = 0; int i = 0;