From 0b1563b66bffb58c30edc163a66bc8fcb7a97f59 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Thu, 13 Feb 2020 02:59:07 +0700 Subject: [PATCH] DEFER: more defer types --- headers/enduro2d/utils/defer.hpp | 57 ++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/headers/enduro2d/utils/defer.hpp b/headers/enduro2d/utils/defer.hpp index 8c1e0e56..8b04a517 100644 --- a/headers/enduro2d/utils/defer.hpp +++ b/headers/enduro2d/utils/defer.hpp @@ -18,19 +18,72 @@ namespace e2d explicit defer_impl(F f) : f_(std::move(f)) {} - ~defer_impl() noexcept(std::is_nothrow_invocable_v) { + ~defer_impl() noexcept { f_(); } private: F f_; }; + + template < typename F > + class error_defer_impl final : noncopyable { + public: + explicit error_defer_impl(F f) + : f_(std::move(f)) + , exceptions_(std::uncaught_exceptions()) {} + + ~error_defer_impl() noexcept { + if ( exceptions_ != std::uncaught_exceptions() ) { + f_(); + } + } + private: + F f_{}; + int exceptions_{}; + }; + + template < typename F > + class return_defer_impl final : noncopyable { + public: + explicit return_defer_impl(F f) + : f_(std::move(f)) + , exceptions_(std::uncaught_exceptions()) {} + + ~return_defer_impl() noexcept { + if ( exceptions_ == std::uncaught_exceptions() ) { + f_(); + } + } + private: + F f_{}; + int exceptions_{}; + }; } template < typename F > impl::defer_impl> make_defer(F&& f) { return impl::defer_impl>(std::forward(f)); } + + template < typename F > + impl::error_defer_impl> make_error_defer(F&& f) { + return impl::error_defer_impl>(std::forward(f)); + } + + template < typename F > + impl::return_defer_impl> make_return_defer(F&& f) { + return impl::return_defer_impl>(std::forward(f)); + } } #define E2D_DEFER(lambda)\ - auto E2D_PP_CAT(e2d_generated_defer_, __LINE__) = ::e2d::make_defer(lambda) + auto E2D_PP_CAT(e2d_generated_defer_, __LINE__) =\ + ::e2d::make_defer(lambda) + +#define E2D_ERROR_DEFER(lambda)\ + auto E2D_PP_CAT(e2d_generated_error_defer_, __LINE__) =\ + ::e2d::make_error_defer(lambda) + +#define E2D_RETURN_DEFER(lambda)\ + auto E2D_PP_CAT(e2d_generated_return_defer_, __LINE__) =\ + ::e2d::make_return_defer(lambda)