From 422e7164d53627650d2772c08c27b6b65920bc49 Mon Sep 17 00:00:00 2001 From: john-lynch Date: Mon, 28 Sep 2015 23:40:25 -0500 Subject: [PATCH 1/3] Fixing move constructor of Final_act to take non-const r-value reference and move properly from other Final_act object so that correctness is not dependent on copy elison. --- include/gsl.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/gsl.h b/include/gsl.h index a73db6b..6de3780 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -50,16 +50,17 @@ template class Final_act { public: - explicit Final_act(F f) : f_(std::move(f)) {} - - Final_act(const Final_act&& other) : f_(other.f_) {} + explicit Final_act(F f) : f_(std::move(f)), invoke_(true) {} + + Final_act(Final_act&& other) : f_(std::move(other.f_)), invoke_(true) { other._invoke = false; } Final_act(const Final_act&) = delete; Final_act& operator=(const Final_act&) = delete; - - ~Final_act() { f_(); } + + ~Final_act() { if (invoke_) f_(); } private: F f_; + bool invoke_; }; // finally() - convenience function to generate a Final_act From 1d11cd1ed13593f5892aff847dfbb42b85a04037 Mon Sep 17 00:00:00 2001 From: john-lynch Date: Tue, 29 Sep 2015 00:00:21 -0500 Subject: [PATCH 2/3] Fixing typo in move constructor implementation that resulted in compile error during tests. --- include/gsl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gsl.h b/include/gsl.h index 6de3780..95116dc 100644 --- a/include/gsl.h +++ b/include/gsl.h @@ -52,7 +52,7 @@ class Final_act public: explicit Final_act(F f) : f_(std::move(f)), invoke_(true) {} - Final_act(Final_act&& other) : f_(std::move(other.f_)), invoke_(true) { other._invoke = false; } + Final_act(Final_act&& other) : f_(std::move(other.f_)), invoke_(true) { other.invoke_ = false; } Final_act(const Final_act&) = delete; Final_act& operator=(const Final_act&) = delete; From ae24c0fe06f92a2a77fb4dbd0098335519a54390 Mon Sep 17 00:00:00 2001 From: john-lynch Date: Tue, 29 Sep 2015 00:03:15 -0500 Subject: [PATCH 3/3] Added test that Final_act object can be moved properly. While this is not a common case, it may happen if the user calls finally and the compiler fails to perform RVO. --- tests/utils_tests.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/utils_tests.cpp b/tests/utils_tests.cpp index 0dc4809..66b6d14 100644 --- a/tests/utils_tests.cpp +++ b/tests/utils_tests.cpp @@ -37,6 +37,20 @@ SUITE(utils_tests) CHECK(i == 1); } + TEST(finally_lambda_move) + { + int i = 0; + { + auto _1 = finally([&]() {f(i);}); + { + auto _2 = std::move(_1); + CHECK(i == 0); + } + CHECK(i == 1); + } + CHECK(i == 1); + } + TEST(finally_function_with_bind) { int i = 0;