diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d2ef82b..b0f67f4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,6 +1,7 @@ name: Test on: + workflow_dispatch: pull_request: push: branches: [ "main" ] @@ -21,16 +22,31 @@ jobs: - os: ubuntu-latest compiler: g++-11 install: g++-11 + - os: ubuntu-latest + compiler: g++-14 + install: g++-14 extra_build_flags: -DENABLE_COVERAGE:BOOL=ON # coverage build - os: ubuntu-20.04 compiler: clang++-7 install: clang-7 - - os: ubuntu-latest + - os: ubuntu-21.04 compiler: clang++-12 - - os: ubuntu-latest + install: clang-12 + - os: ubuntu-21.04 compiler: clang++-13 + install: clang-13 - os: ubuntu-latest compiler: clang++-14 + install: clang-14 + - os: ubuntu-latest + compiler: clang++-15 + install: clang-15 + - os: ubuntu-latest + compiler: clang++-16 + install: clang-16 + - os: ubuntu-latest + compiler: clang++-18 + install: clang-18 - os: macos-11 compiler: g++-10 - os: macos-latest diff --git a/scope_guard.hpp b/scope_guard.hpp index 3d67d79..5913b59 100644 --- a/scope_guard.hpp +++ b/scope_guard.hpp @@ -8,6 +8,7 @@ #ifndef SCOPE_GUARD_HPP_ #define SCOPE_GUARD_HPP_ +#include #include #include @@ -22,6 +23,13 @@ namespace sg { + enum class ExitType { + ALWAYS, +#if __cplusplus >= 201411L + ON_SUCCESS, + ON_FAILURE, +#endif + }; namespace detail { /* --- Some custom type traits --- */ @@ -76,10 +84,29 @@ namespace sg std::is_nothrow_destructible> {}; + template struct ShouldRun; + template<> struct ShouldRun { + constexpr static bool should_run() { return true; } + }; +#if __cplusplus >= 201703L + template<> struct ShouldRun { + static bool should_run() { return std::uncaught_exceptions() == 0; } + }; + template<> struct ShouldRun { + static bool should_run() { return std::uncaught_exceptions() != 0; } + }; +#elif __cplusplus >= 201411L + template<> struct ShouldRun { + static bool should_run() { return !std::uncaught_exception(); } + }; + template<> struct ShouldRun { + static bool should_run() { return std::uncaught_exception(); } + }; +#endif /* --- The actual scope_guard template --- */ - template::value>::type> class scope_guard; @@ -97,8 +124,8 @@ namespace sg /* --- The template specialization that actually defines the class --- */ - template - class SG_NODISCARD scope_guard final + template + class SG_NODISCARD scope_guard final { public: typedef Callback callback_type; @@ -142,8 +169,8 @@ namespace sg } // namespace sg //////////////////////////////////////////////////////////////////////////////// -template -sg::detail::scope_guard::scope_guard(Callback&& callback) +template +sg::detail::scope_guard::scope_guard(Callback&& callback) noexcept(std::is_nothrow_constructible::value) : m_callback(std::forward(callback)) /* use () instead of {} because of DR 1467 (https://is.gd/WHmWuo), which still impacts older compilers @@ -153,17 +180,17 @@ noexcept(std::is_nothrow_constructible::value) {} //////////////////////////////////////////////////////////////////////////////// -template -sg::detail::scope_guard::scope_guard::~scope_guard() noexcept /* +template +sg::detail::scope_guard::scope_guard::~scope_guard() noexcept /* need the extra injected-class-name here to make different compilers happy */ { - if(m_active) + if(m_active && ShouldRun::should_run()) m_callback(); } //////////////////////////////////////////////////////////////////////////////// -template -sg::detail::scope_guard::scope_guard(scope_guard&& other) +template +sg::detail::scope_guard::scope_guard(scope_guard&& other) noexcept(std::is_nothrow_constructible::value) : m_callback(std::forward(other.m_callback)) // idem , m_active{std::move(other.m_active)} @@ -172,19 +199,19 @@ noexcept(std::is_nothrow_constructible::value) } //////////////////////////////////////////////////////////////////////////////// -template -inline void sg::detail::scope_guard::dismiss() noexcept +template +inline void sg::detail::scope_guard::dismiss() noexcept { m_active = false; } //////////////////////////////////////////////////////////////////////////////// -template +template inline auto sg::detail::make_scope_guard(Callback&& callback) noexcept(std::is_nothrow_constructible::value) --> detail::scope_guard +-> detail::scope_guard { - return detail::scope_guard{std::forward(callback)}; + return detail::scope_guard{std::forward(callback)}; } #endif /* SCOPE_GUARD_HPP_ */