summaryrefslogtreecommitdiff
path: root/zen/scope_guard.h
diff options
context:
space:
mode:
Diffstat (limited to 'zen/scope_guard.h')
-rw-r--r--zen/scope_guard.h64
1 files changed, 43 insertions, 21 deletions
diff --git a/zen/scope_guard.h b/zen/scope_guard.h
index 67eb3053..f8c32127 100644
--- a/zen/scope_guard.h
+++ b/zen/scope_guard.h
@@ -22,7 +22,7 @@ inline int getUncaughtExceptionCount() { return std::uncaught_exceptions(); }
#ifdef ZEN_LINUX
static_assert(__GNUC__ < 5 || (__GNUC__ == 5 && (__GNUC_MINOR__ < 3 || (__GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ <= 1))), "check std::uncaught_exceptions support");
#else
- static_assert(__clang_major__ < 7 || (__clang_major__ == 7 && __clang_minor__ <= 0), "check std::uncaught_exceptions support");
+ static_assert(__clang_major__ < 7 || (__clang_major__ == 7 && __clang_minor__ <= 3), "check std::uncaught_exceptions support");
#endif
namespace __cxxabiv1
@@ -61,6 +61,47 @@ enum class ScopeGuardRunMode
template <ScopeGuardRunMode runMode, typename F>
+struct ScopeGuardDestructor;
+
+//specialize scope guard destructor code and get rid of those pesky MSVC "4127 conditional expression is constant"
+template <typename F>
+struct ScopeGuardDestructor<ScopeGuardRunMode::ON_EXIT, F>
+{
+ static void run(F& fun, int exeptionCountOld)
+ {
+ (void)exeptionCountOld; //silence unused parameter warning
+ try { fun(); }
+ catch (...) { assert(false); } //consistency: don't expect exceptions for ON_EXIT even if "!failed"!
+ }
+};
+
+
+template <typename F>
+struct ScopeGuardDestructor<ScopeGuardRunMode::ON_SUCCESS, F>
+{
+ static void run(F& fun, int exeptionCountOld)
+ {
+ const bool failed = getUncaughtExceptionCount() > exeptionCountOld;
+ if (!failed)
+ fun(); //throw X
+ }
+};
+
+
+template <typename F>
+struct ScopeGuardDestructor<ScopeGuardRunMode::ON_FAIL, F>
+{
+ static void run(F& fun, int exeptionCountOld)
+ {
+ const bool failed = getUncaughtExceptionCount() > exeptionCountOld;
+ if (failed)
+ try { fun(); }
+ catch (...) { assert(false); }
+ }
+};
+
+
+template <ScopeGuardRunMode runMode, typename F>
class ScopeGuard
{
public:
@@ -74,26 +115,7 @@ public:
~ScopeGuard() noexcept(runMode != ScopeGuardRunMode::ON_SUCCESS)
{
if (!dismissed)
- {
-#ifdef _MSC_VER
-#pragma warning(suppress: 4127) //"conditional expression is constant"
-#endif
- if (runMode != ScopeGuardRunMode::ON_EXIT)
- {
- const bool failed = getUncaughtExceptionCount() > exeptionCount;
- if ((runMode == ScopeGuardRunMode::ON_FAIL) != failed)
- return;
- }
-
-#ifdef _MSC_VER
-#pragma warning(suppress: 4127) //"conditional expression is constant"
-#endif
- if (runMode == ScopeGuardRunMode::ON_SUCCESS)
- fun_(); //throw X
- else
- try { fun_(); }
- catch (...) { assert(false); } //consistency: don't expect exceptions for ON_EXIT even if "!failed"!
- }
+ ScopeGuardDestructor<runMode, F>::run(fun_, exeptionCount);
}
void dismiss() { dismissed = true; }
bgstack15