FinallyScopeExit

對於我們不想編寫特殊類來處理某些資源的情況,我們可以編寫一個泛型類:

template<typename Function>
class Finally final
{
public:
    explicit Finally(Function f) : f(std::move(f)) {}
    ~Finally() { f(); } // (1) See below

    Finally(const Finally&) = delete;
    Finally(Finally&&) = default;
    Finally& operator =(const Finally&) = delete;
    Finally& operator =(Finally&&) = delete;
private:
    Function f;
};
// Execute the function f when the returned object goes out of scope.
template<typename Function>
auto onExit(Function &&f) { return Finally<std::decay_t<Function>>{std::forward<Function>(f)}; }

它的示例用法

void foo(std::vector<int>& v, int i)
{
    // ...

    v[i] += 42;
    auto autoRollBackChange = onExit([&](){ v[i] -= 42; });

    // ... code as recursive call `foo(v, i + 1)`
}

注意(1):必須考慮一些關於解構函式定義的討論來處理異常:

  • ~Finally() noexcept { f(); }:在例外的情況下呼叫 std::terminate
  • ~Finally() noexcept(noexcept(f())) { f(); }:僅在堆疊展開期間發生異常時呼叫 terminate()
  • ~Finally() noexcept { try { f(); } catch (...) { /* ignore exception (might log it) */} } 沒有 std::terminate 呼叫,但是我們無法處理錯誤(即使是非堆疊展開)。