diff --git a/headers/defer.hpp/defer.hpp b/headers/defer.hpp/defer.hpp index 5038a3e..42ca7e8 100644 --- a/headers/defer.hpp/defer.hpp +++ b/headers/defer.hpp/defer.hpp @@ -11,143 +11,140 @@ #include #include +namespace defer_hpp::impl +{ + template < typename F, typename... Args > + class defer_impl { + public: + defer_impl() = delete; + defer_impl(defer_impl&&) = delete; + defer_impl(const defer_impl&) = delete; + defer_impl& operator=(defer_impl&&) = delete; + defer_impl& operator=(const defer_impl&) = delete; + + template < typename UF > + explicit defer_impl(UF&& f, std::tuple&& args) + : f_{std::forward(f)} + , args_{std::move(args)} {} + + void dismiss() noexcept { + dismissed_ = true; + } + + protected: + ~defer_impl() noexcept { + if ( !dismissed_ ) { + std::apply(std::move(f_), std::move(args_)); + } + } + + private: + F f_; + std::tuple args_; + bool dismissed_{}; + }; +} + namespace defer_hpp { - namespace impl - { - template < typename F, typename... Args > - class base_defer_t { - public: - base_defer_t() = delete; - base_defer_t(base_defer_t&&) = delete; - base_defer_t(const base_defer_t&) = delete; - base_defer_t& operator=(base_defer_t&&) = delete; - base_defer_t& operator=(const base_defer_t&) = delete; + template < typename F, typename... Args > + class defer final : public impl::defer_impl { + public: + defer() = delete; + defer(defer&&) = delete; + defer(const defer&) = delete; + defer& operator=(defer&&) = delete; + defer& operator=(const defer&) = delete; - template < typename UF > - explicit base_defer_t(UF&& f, std::tuple&& args) - : f_{std::forward(f)} - , args_{std::move(args)} {} + template < typename UF > + explicit defer(UF&& f, std::tuple&& args) + : impl::defer_impl{std::forward(f), std::move(args)} {} - void dismiss() noexcept { - dismissed_ = true; + ~defer() noexcept = default; + }; + + template < typename F, typename... Args > + class error_defer final : public impl::defer_impl { + public: + error_defer() = delete; + error_defer(error_defer&&) = delete; + error_defer(const error_defer&) = delete; + error_defer& operator=(error_defer&&) = delete; + error_defer& operator=(const error_defer&) = delete; + + template < typename UF > + explicit error_defer(UF&& f, std::tuple&& args) + : impl::defer_impl{std::forward(f), std::move(args)} + , exceptions_{std::uncaught_exceptions()} {} + + ~error_defer() noexcept { + if ( exceptions_ == std::uncaught_exceptions() ) { + this->dismiss(); } + } - protected: - ~base_defer_t() noexcept { - if ( !dismissed_ ) { - std::apply(std::move(f_), std::move(args_)); - } + private: + int exceptions_{}; + }; + + template < typename F, typename... Args > + class return_defer final : public impl::defer_impl { + public: + return_defer() = delete; + return_defer(return_defer&&) = delete; + return_defer(const return_defer&) = delete; + return_defer& operator=(return_defer&&) = delete; + return_defer& operator=(const return_defer&) = delete; + + template < typename UF > + explicit return_defer(UF&& f, std::tuple&& args) + : impl::defer_impl{std::forward(f), std::move(args)} + , exceptions_{std::uncaught_exceptions()} {} + + ~return_defer() noexcept { + if ( exceptions_ != std::uncaught_exceptions() ) { + this->dismiss(); } + } - private: - F f_; - std::tuple args_; - bool dismissed_{}; - }; - } - - namespace impl - { - template < typename F, typename... Args > - class defer_t final : public base_defer_t { - public: - defer_t() = delete; - defer_t(defer_t&&) = delete; - defer_t(const defer_t&) = delete; - defer_t& operator=(defer_t&&) = delete; - defer_t& operator=(const defer_t&) = delete; - - template < typename UF > - explicit defer_t(UF&& f, std::tuple&& args) - : base_defer_t{std::forward(f), std::move(args)} {} - - ~defer_t() noexcept = default; - }; - - template < typename F, typename... Args > - class error_defer_t final : public base_defer_t { - public: - error_defer_t() = delete; - error_defer_t(error_defer_t&&) = delete; - error_defer_t(const error_defer_t&) = delete; - error_defer_t& operator=(error_defer_t&&) = delete; - error_defer_t& operator=(const error_defer_t&) = delete; - - template < typename UF > - explicit error_defer_t(UF&& f, std::tuple&& args) - : base_defer_t{std::forward(f), std::move(args)} - , exceptions_{std::uncaught_exceptions()} {} - - ~error_defer_t() noexcept { - if ( exceptions_ == std::uncaught_exceptions() ) { - this->dismiss(); - } - } - - private: - int exceptions_{}; - }; - - template < typename F, typename... Args > - class return_defer_t final : public base_defer_t { - public: - return_defer_t() = delete; - return_defer_t(return_defer_t&&) = delete; - return_defer_t(const return_defer_t&) = delete; - return_defer_t& operator=(return_defer_t&&) = delete; - return_defer_t& operator=(const return_defer_t&) = delete; - - template < typename UF > - explicit return_defer_t(UF&& f, std::tuple&& args) - : base_defer_t{std::forward(f), std::move(args)} - , exceptions_{std::uncaught_exceptions()} {} - - ~return_defer_t() noexcept { - if ( exceptions_ != std::uncaught_exceptions() ) { - this->dismiss(); - } - } - - private: - int exceptions_{}; - }; - } + private: + int exceptions_{}; + }; template < typename F, typename... Args > auto make_defer(F&& f, Args&&... args) { - using defer_t = impl::defer_t, std::decay_t...>; + using defer_t = defer, std::decay_t...>; return defer_t{std::forward(f), std::make_tuple(std::forward(args)...)}; } template < typename F, typename... Args > auto make_error_defer(F&& f, Args&&... args) { - using defer_t = impl::error_defer_t, std::decay_t...>; + using defer_t = error_defer, std::decay_t...>; return defer_t{std::forward(f), std::make_tuple(std::forward(args)...)}; } template < typename F, typename... Args > auto make_return_defer(F&& f, Args&&... args) { - using defer_t = impl::return_defer_t, std::decay_t...>; + using defer_t = return_defer, std::decay_t...>; return defer_t{std::forward(f), std::make_tuple(std::forward(args)...)}; } } -#define DEFER_HPP_IMPL_PP_CAT(x, y) DEFER_HPP_IMPL_PP_CAT_I(x, y) -#define DEFER_HPP_IMPL_PP_CAT_I(x, y) x##y +#define DEFER_HPP_PP_CAT(x, y) DEFER_HPP_PP_CAT_I(x, y) +#define DEFER_HPP_PP_CAT_I(x, y) x##y #ifdef __COUNTER__ # define DEFER_HPP(...) \ - auto DEFER_HPP_IMPL_PP_CAT(defer_hpp_generated_defer_, __COUNTER__) { ::defer_hpp::make_defer(__VA_ARGS__) } + auto DEFER_HPP_PP_CAT(defer_hpp_generated_defer_, __COUNTER__) { ::defer_hpp::make_defer(__VA_ARGS__) } # define ERROR_DEFER_HPP(...) \ - auto DEFER_HPP_IMPL_PP_CAT(defer_hpp_generated_error_defer_, __COUNTER__) { ::defer_hpp::make_error_defer(__VA_ARGS__) } + auto DEFER_HPP_PP_CAT(defer_hpp_generated_error_defer_, __COUNTER__) { ::defer_hpp::make_error_defer(__VA_ARGS__) } # define RETURN_DEFER_HPP(...) \ - auto DEFER_HPP_IMPL_PP_CAT(defer_hpp_generated_return_defer_, __COUNTER__) { ::defer_hpp::make_return_defer(__VA_ARGS__) } + auto DEFER_HPP_PP_CAT(defer_hpp_generated_return_defer_, __COUNTER__) { ::defer_hpp::make_return_defer(__VA_ARGS__) } #else # define DEFER_HPP(...) \ - auto DEFER_HPP_IMPL_PP_CAT(defer_hpp_generated_defer_, __LINE__) { ::defer_hpp::make_defer(__VA_ARGS__) } + auto DEFER_HPP_PP_CAT(defer_hpp_generated_defer_, __LINE__) { ::defer_hpp::make_defer(__VA_ARGS__) } # define ERROR_DEFER_HPP(...) \ - auto DEFER_HPP_IMPL_PP_CAT(defer_hpp_generated_error_defer_, __LINE__) { ::defer_hpp::make_error_defer(__VA_ARGS__) } + auto DEFER_HPP_PP_CAT(defer_hpp_generated_error_defer_, __LINE__) { ::defer_hpp::make_error_defer(__VA_ARGS__) } # define RETURN_DEFER_HPP(...) \ - auto DEFER_HPP_IMPL_PP_CAT(defer_hpp_generated_return_defer_, __LINE__) { ::defer_hpp::make_return_defer(__VA_ARGS__) } + auto DEFER_HPP_PP_CAT(defer_hpp_generated_return_defer_, __LINE__) { ::defer_hpp::make_return_defer(__VA_ARGS__) } #endif