scope_guard

ScopeGuard - Faith and Brave - C++で遊ぼう を見て、面白そうなので C++0x で書いたらどうなるかなーと思ってやってみた。

class scope_guard_impl_base
{
protected:
    scope_guard_impl_base() : dismissed_(false) { }
    scope_guard_impl_base(const scope_guard_impl_base&) = delete;
    scope_guard_impl_base& operator=(const scope_guard_impl_base&) = delete;

    mutable bool dismissed_;

public:
    void dismiss() const { dismissed_ = true; }
};

template<class F>
class scope_guard_impl : scope_guard_impl_base
{
    F f_;
public:
    scope_guard_impl(F f) : f_(std::move(f)) { }
    scope_guard_impl(const scope_guard_impl&) = delete;
    scope_guard_impl& operator=(const scope_guard_impl&) = delete;

    ~scope_guard_impl() { if (!dismissed_) f_(); }
};

template<class F>
scope_guard_impl<F> make_guard(F f)
{
    return scope_guard_impl<F>(std::move(f));
}
typedef const scope_guard_impl_base& scope_guard;
int main()
{
    FILE *fp = std::fopen(R"[C:\a.txt]", "wb");
    scope_guard guard = make_guard([&fp] { if (fp != nullptr) std::fclose(fp); });

    // ファイル(fp)を使った処理...
    std::string str = "abc";
    std::fwrite(str.c_str(), str.length(), 1, fp);

    return 0; // ←ここでfcloseされる
}

const で受け取っているから mutable にしている部分とかきもいなぁとか思ったりするけどそこら辺は気にしない。
あとムーブ先生とラムダ先生が素敵すぎます。


で、C++0x は auto があるので const Base& とか持たなくても、

template<class F>
class scope_guard
{
    F f_;
    bool dismissed_;

public:
    scope_guard(F f) : f_(std::move(f)), dismissed_(false) { }
    scope_guard(const scope_guard_t&) = delete;
    ~scope_guard() { if (!dismissed_) f_(); }
    dismiss() { dismissed_ = true; }
};

template<class F>
scope_guard<F> make_guard(F f)
{
    return scope_guard<F>(std::move(f));
}

これだけで、あとは

auto guard = make_guard([&fp] { if (fp != nullptr) std::fclose(fp); });

と書くだけで良かったり。オート先生万歳です。