/// \file // Range v3 library // // Copyright Eric Niebler 2017-present // // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Project home: https://github.com/ericniebler/range-v3 // #ifndef RANGES_V3_UTILITY_SCOPE_EXIT_HPP #define RANGES_V3_UTILITY_SCOPE_EXIT_HPP #include #include #include #include namespace ranges { template struct scope_exit { private: using nothrow_move_t = std::is_nothrow_move_constructible; using nothrow_copy_t = std::is_nothrow_copy_constructible; Fun fun_; bool dismissed_{false}; using ref_t = decltype(std::ref(std::declval())); using guard = scope_exit; scope_exit(Fun const & fun, guard && g) : fun_(fun) { g.dismiss(); } scope_exit(Fun const & fun, std::false_type) : scope_exit(fun, guard{std::ref(fun)}) {} scope_exit(Fun const & fun, std::true_type) noexcept : fun_(fun) {} scope_exit(Fun && fun, std::true_type) noexcept : fun_(std::move(fun)) {} public: explicit scope_exit(Fun const & fun) noexcept( noexcept(scope_exit(fun, nothrow_copy_t{}))) : scope_exit(fun, nothrow_copy_t{}) {} explicit scope_exit(Fun && fun) noexcept(noexcept(scope_exit(std::move(fun), nothrow_move_t{}))) : scope_exit(std::move(fun), nothrow_move_t{}) {} scope_exit(scope_exit const &) = delete; scope_exit(scope_exit && that) noexcept( std::is_nothrow_move_constructible::value) : scope_exit(std::move((that.dismiss(), that)).fun_) {} ~scope_exit() { if(!dismissed_) fun_(); } void dismiss() noexcept { dismissed_ = true; } }; template>>> ScopeExit make_scope_exit(Fun && fun) noexcept( noexcept(ScopeExit(ScopeExit((Fun &&) fun)))) { return ScopeExit((Fun &&) fun); } } // namespace ranges #endif