Skip to content

Commit

Permalink
constepxr scope guards (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
Morwenn committed Oct 23, 2022
1 parent e513e56 commit c1e1725
Showing 1 changed file with 27 additions and 14 deletions.
41 changes: 27 additions & 14 deletions include/cpp-sort/detail/scope_exit.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@

namespace cppsort::detail
{
constexpr auto uncaught_exceptions() noexcept
-> int
{
if (std::is_constant_evaluated()) {
// Throwing an exception at compile time terminates the
// compilation process, so there can never be an exception
// in flight in a constant-evaluated expressions
return 0;
} else {
return std::uncaught_exceptions();
}
}

template<typename EF>
struct scope_exit
{
Expand All @@ -25,33 +38,33 @@ namespace cppsort::detail
public:

template<typename EFP>
explicit scope_exit(EFP&& func)
constexpr explicit scope_exit(EFP&& func)
noexcept(std::is_nothrow_constructible_v<EF, EFP> ||
std::is_nothrow_constructible_v<EF, EFP&>):
exit_function(std::forward<EFP>(func))
{}

scope_exit(scope_exit&& rhs)
constexpr scope_exit(scope_exit&& rhs)
noexcept(std::is_nothrow_move_constructible_v<EF> ||
std::is_nothrow_copy_constructible_v<EF>):
exit_function(std::forward<EF>(rhs.exit_function))
{}

~scope_exit()
constexpr ~scope_exit()
noexcept(noexcept(exit_function()))
{
if (execute_on_destruction) {
exit_function();
}
}

auto activate() noexcept
constexpr auto activate() noexcept
-> void
{
execute_on_destruction = true;
}

auto deactivate() noexcept
constexpr auto deactivate() noexcept
-> void
{
execute_on_destruction = false;
Expand All @@ -63,7 +76,7 @@ namespace cppsort::detail
};

template<typename EF>
auto make_scope_exit(EF&& function)
constexpr auto make_scope_exit(EF&& function)
-> scope_exit<EF>
{
return scope_exit<EF>(std::forward<EF>(function));
Expand All @@ -76,38 +89,38 @@ namespace cppsort::detail

EF exit_function;
bool execute_on_destruction = true;
int uncaught_on_creation = std::uncaught_exceptions();
int uncaught_on_creation = uncaught_exceptions();

public:

template<typename EFP>
explicit scope_success(EFP&& func)
constexpr explicit scope_success(EFP&& func)
noexcept(std::is_nothrow_constructible_v<EF, EFP> ||
std::is_nothrow_constructible_v<EF, EFP&>):
exit_function(std::forward<EFP>(func))
{}

scope_success(scope_success&& rhs)
constexpr scope_success(scope_success&& rhs)
noexcept(std::is_nothrow_move_constructible_v<EF> ||
std::is_nothrow_copy_constructible_v<EF>):
exit_function(std::forward<EF>(rhs.exit_function))
{}

~scope_success()
constexpr ~scope_success()
noexcept(noexcept(exit_function()))
{
if (execute_on_destruction && std::uncaught_exceptions() <= uncaught_on_creation) {
if (execute_on_destruction && uncaught_exceptions() <= uncaught_on_creation) {
exit_function();
}
}

auto activate() noexcept
constexpr auto activate() noexcept
-> void
{
execute_on_destruction = true;
}

auto deactivate() noexcept
constexpr auto deactivate() noexcept
-> void
{
execute_on_destruction = false;
Expand All @@ -119,7 +132,7 @@ namespace cppsort::detail
};

template<typename EF>
auto make_scope_success(EF&& function)
constexpr auto make_scope_success(EF&& function)
-> scope_success<EF>
{
return scope_success<EF>(std::forward<EF>(function));
Expand Down

0 comments on commit c1e1725

Please sign in to comment.