Skip to content

Instantly share code, notes, and snippets.

@PkmX
Last active December 10, 2015 20:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PkmX/4491652 to your computer and use it in GitHub Desktop.
Save PkmX/4491652 to your computer and use it in GitHub Desktop.
#ifndef SCOPEGUARD_HPP
#define SCOPEGUARD_HPP
#include <functional>
#ifndef __has_feature
#define __has_feature(x) 0
#endif
namespace detail
{
template<typename F>
class scopeguard_impl
{
public:
explicit scopeguard_impl(F&& f_)
: f(std::forward<F>(f_)), dismissed(false)
{
}
// Note: defining a move constructor inhibits auto-generation of copy constructor and copy assignment operator.
scopeguard_impl(scopeguard_impl&& rhs)
: f(std::move(rhs.f)), dismissed(std::move(rhs.dismissed))
{
rhs.dismiss();
}
#if __has_feature(cxx_reference_qualified_functions)
scopeguard_impl& operator=(scopeguard_impl&& rhs) &
#else
scopeguard_impl& operator=(scopeguard_impl&& rhs)
#endif
{
this->f = std::move(rhs.f);
this->dismissed = std::move(rhs.dismissed);
rhs.dismiss();
return *this;
}
~scopeguard_impl()
{
if (!this->dismissed)
{
this->f();
}
}
void dismiss()
{
this->dismissed = true;
}
private:
F f;
bool dismissed;
// Prevent scopeguard from being new'ed.
void* operator new(std::size_t) = delete;
void* operator new[](std::size_t) = delete;
void operator delete(void*) = delete;
void operator delete[](void*) = delete;
};
}
template<typename F>
detail::scopeguard_impl<F> scopeguard(F&& f)
{
return detail::scopeguard_impl<F>(std::forward<F>(f));
}
#define SCOPEGUARD_PP_CAT_IMPL(x, y) x##y
#define SCOPEGUARD_PP_CAT(x, y) SCOPEGUARD_PP_CAT_IMPL(x, y)
#define at_scope_exit(f) \
__attribute__((unused)) const auto SCOPEGUARD_PP_CAT(scopeguard, __COUNTER__) = scopeguard((f));
#endif // SCOPEGUARD_HPP
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment