Since you want to use it only as ScopeGuard - then you can be sure that the link to const or rvalue to your close() valid. You need a member or base class, as in the other answer, but that is not a very big difference. But you can use it as a reference to your lambda, and not to std::function , which has pretty high performance:
template <class Close> class ScopeGuard { public: template <typename Open> ScopeGuard(Open&& open, Close&& close) : close(std::forward<Close>(close)) { open(); } ScopeGuard(ScopeGuard&& other) : close(std::move(other.close)) {} ~ScopeGuard() { close(); } private: Close&& close; };
To make it easier to use, use this make function:
template <class Open, class Close> auto makeScopeGuard(Open&& open, Close&& close) { return ScopeGuard<Close>(std::forward<Open>(open), std::forward<Close>(close)); }
And use:
#include <iostream> using namespace std; int main() { int i = 0; auto scope = makeScopeGuard([&i]{cout << "Open " << i++ << "\n";}, [&i]{cout << "Close " << i++ << "\n";}); cout << "Body\n"; }
Conclusion:
Open 0 Body Close 1
I checked that it works for gcc and clang, C ++ 14 with no errors / warnings.
source share