This is actually not something new, but I think many people wanted something useful and not incredibly complicated. So, here it is:
#pragma once
#include <utility>
#define concat_impl(x, y) x##y
#define concat(x, y) concat_impl(x, y)
#ifdef __COUNTER__
#define ANONYMOUS_VARIABLE(NAME) concat(NAME, __COUNTER__)
#else
#define ANONYMOUS_VARIABLE(NAME) concat(NAME, __LINE__)
#endif
namespace detail
{
template <typename Func>
class ScopeGuardOnExit
{
Func f;
public:
ScopeGuardOnExit(Func&& f) :
f(std::forward<Func>(f))
{}
~ScopeGuardOnExit()
{
f();
}
};
struct dummy {};
template <typename Func>
ScopeGuardOnExit<Func> operator+(dummy, Func&& f)
{
return std::forward<Func>(f);
}
}
#define scope_exit \
auto ANONYMOUS_VARIABLE(SCOPE_EXIT_WHATEVER) = ::detail::dummy() + [&]()
Usage:
#include "scope_exit.hpp"
#include <iostream>
int f()
{
scope_exit {std::cout << "exiting f()\n";};
return 0;
}
int main()
{
f();
scope_exit {std::cout << "It's working!\n";};
}
Do note that the lambda takes (pulls into abyss) everything by reference. On top of that, it is possible to register multiple function to execute at exit. Is it possible to make it more user friendly? The best would be to try to write it using templates.
By being more user friendly I mean eliminating that SCOPE_EXIT_WHATEVERN
variable from the variable list for the current scope, because people will get surprised when they will see it in an IDE. Also, forgetting semicolon ;
will lead to pretty confusing error messages.