From 598b373b351e50ff9c576141cf00e174f0a7a6c6 Mon Sep 17 00:00:00 2001 From: Vitaly Baranov Date: Thu, 5 Mar 2020 17:42:02 +0300 Subject: [PATCH] Improve ext::scope_guard. --- base/ext/scope_guard.h | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/base/ext/scope_guard.h b/base/ext/scope_guard.h index f5b986e7ab6..79bad56f360 100644 --- a/base/ext/scope_guard.h +++ b/base/ext/scope_guard.h @@ -12,20 +12,20 @@ class [[nodiscard]] basic_scope_guard { public: constexpr basic_scope_guard() = default; - constexpr basic_scope_guard(basic_scope_guard && src) : function{std::exchange(src.function, {})} {} + constexpr basic_scope_guard(basic_scope_guard && src) : function{src.release()} {} constexpr basic_scope_guard & operator=(basic_scope_guard && src) { if (this != &src) { invoke(); - function = std::exchange(src.function, {}); + function = src.release(); } return *this; } template , void>> - constexpr basic_scope_guard(basic_scope_guard && src) : function{std::exchange(src.function, {})} {} + constexpr basic_scope_guard(basic_scope_guard && src) : function{src.release()} {} template , void>> constexpr basic_scope_guard & operator=(basic_scope_guard && src) @@ -33,7 +33,7 @@ public: if (this != &src) { invoke(); - function = std::exchange(src.function, {}); + function = src.release(); } return *this; } @@ -46,14 +46,26 @@ public: ~basic_scope_guard() { invoke(); } + static constexpr bool is_nullable = std::is_constructible_v; + explicit operator bool() const { - if constexpr (std::is_constructible_v) + if constexpr (is_nullable) return static_cast(function); return true; } - void reset() { function = {}; } + void reset() + { + invoke(); + release(); + } + + F release() + { + static_assert(is_nullable); + return std::exchange(function, {}); + } template , void>> basic_scope_guard & join(basic_scope_guard && other) @@ -62,14 +74,14 @@ public: { if (function) { - function = [x = std::make_shared>(std::move(function), std::exchange(other.function, {}))]() + function = [x = std::make_shared>(std::move(function), other.release())]() { std::move(x->first)(); std::move(x->second)(); }; } else - function = std::exchange(other.function, {}); + function = other.release(); } return *this; } @@ -77,7 +89,7 @@ public: private: void invoke() { - if constexpr (std::is_constructible_v) + if constexpr (is_nullable) { if (!function) return;