diff --git a/base/include/android-base/scopeguard.h b/base/include/android-base/scopeguard.h index abcf4bca4..c314e0263 100644 --- a/base/include/android-base/scopeguard.h +++ b/base/include/android-base/scopeguard.h @@ -17,20 +17,27 @@ #ifndef ANDROID_BASE_SCOPEGUARD_H #define ANDROID_BASE_SCOPEGUARD_H -#include // for std::move +#include // for std::move, std::forward namespace android { namespace base { +// ScopeGuard ensures that the specified functor is executed no matter how the +// current scope exits. template class ScopeGuard { public: - ScopeGuard(F f) : f_(f), active_(true) {} + ScopeGuard(F&& f) : f_(std::forward(f)), active_(true) {} ScopeGuard(ScopeGuard&& that) : f_(std::move(that.f_)), active_(that.active_) { that.active_ = false; } + template + ScopeGuard(ScopeGuard&& that) : f_(std::move(that.f_)), active_(that.active_) { + that.active_ = false; + } + ~ScopeGuard() { if (active_) f_(); } @@ -45,13 +52,16 @@ class ScopeGuard { bool active() const { return active_; } private: + template + friend class ScopeGuard; + F f_; bool active_; }; -template -ScopeGuard make_scope_guard(T f) { - return ScopeGuard(f); +template +ScopeGuard make_scope_guard(F&& f) { + return ScopeGuard(std::forward(f)); } } // namespace base diff --git a/base/scopeguard_test.cpp b/base/scopeguard_test.cpp index e11154a57..9236d7b78 100644 --- a/base/scopeguard_test.cpp +++ b/base/scopeguard_test.cpp @@ -17,6 +17,7 @@ #include "android-base/scopeguard.h" #include +#include #include @@ -44,3 +45,15 @@ TEST(scopeguard, moved) { EXPECT_FALSE(scopeguard.active()); ASSERT_FALSE(guarded_var); } + +TEST(scopeguard, vector) { + int guarded_var = 0; + { + std::vector>> scopeguards; + scopeguards.emplace_back(android::base::make_scope_guard( + std::bind([](int& guarded_var) { guarded_var++; }, std::ref(guarded_var)))); + scopeguards.emplace_back(android::base::make_scope_guard( + std::bind([](int& guarded_var) { guarded_var++; }, std::ref(guarded_var)))); + } + ASSERT_EQ(guarded_var, 2); +}