I\'ve written a small utility class for C++11 which I use as a scope guard for easier handling of exception safety and similar things.
Seems somewhat like a hack. Bu
The implementation could be very much simplified using tr1::function
and tr1::unique_ptr
, as below:
namespace detail
{
class ScopeGuard
{
public:
explicit ScopeGuard(std::function<void()> onExitScope)
: onExitScope_(onExitScope), dismissed_(false)
{ }
~ScopeGuard()
{
try
{
if(!dismissed_)
{
onExitScope_();
}
}
catch(...){}
}
void Dismiss()
{
dismissed_ = true;
}
private:
std::function<void()> onExitScope_;
bool dismissed_;
// noncopyable
private:
ScopeGuard(ScopeGuard const&);
ScopeGuard& operator=(ScopeGuard const&);
};
}
inline std::unique_ptr<detail::ScopeGuard> CreateScopeGuard(std::function<void()> onExitScope)
{
return std::unique_ptr<detail::ScopeGuard>(new detail::ScopeGuard(onExitScope));
}
But is it a good idea?
Sure. A related topic is the RAII paradigm.
Or are there potential problems I have missed?
You don't handle exceptions.
Is there already a similar solution (with C++0x features) in boost or similar?
Alexandrescu came up with ScopeGuard a long time back. Both Boost and std::tr1
has a thing called scoped_ptr and shared_ptr (with a custom deleter) that allows you to accomplish just this.
This is a good idea, but there are a couple of problems with you class.
notice that if you implement point 2 you need a meaningful name for each scopeguard you instantiate. This is, in general, not a problem, but it could be in your application (or to your taste).
Finally, this question would probably have been more appropriate for CodeReview.
If replace create_scope_exit by a binary operator, we can remove parentheses:
class at_scope_exit
{
template<typename F>
struct scope_exit_fn_holder : boost::noncopyable
{
scope_exit_fn_holder(F&& f) : f(std::forward<F>(f)) {}
F f;
~scope_exit_fn_holder() { f(); }
};
template<typename F>
friend scope_exit_fn_holder<F> operator==(at_scope_exit, F&& f)
{
return scope_exit_fn_holder<F>(std::forward<F>(f));
}
};
Usage:
auto atScopeExit = at_scope_exit() == [&]
{
...
};
upd:
Corresponding macro:
#include <boost/preprocessor/cat.hpp>
#define AT_SCOPE_EXIT auto BOOST_PP_CAT(scopeExit_, __LINE__) = at_scope_exit() == [&]
#define AT_SCOPE_EXIT_EX(...) auto BOOST_PP_CAT(scopeExit_, __LINE__) = at_scope_exit() == [__VA_ARGS__]