読者です 読者をやめる 読者になる 読者になる

C++0xではわりと必須なscope_guard

C++

C++にはScope Guardというイディオムがあります。


関数のスコープ抜けたらこの関数実行してね、というものなのですが
C++0xにはラムダ式が入るので、それを組み合わせれば関数が抜けたときに実行する処理をその場で書くことができます。


でも、Scope Guardは標準では提供されないので、作ってみました。


shand/scope_guard.hpp

#ifndef SHAND_SCOPE_GUARD_INCLUDE
#define SHAND_SCOPE_GUARD_INCLUDE

namespace shand {

namespace detail {

class scope_guard_functor_base {
    bool cancel_;
public:
    scope_guard_functor_base() : cancel_(false) {}
    virtual ~scope_guard_functor_base() {}

    void cancel()
    {
        cancel_ = true;
    }

protected:
    bool is_cancel() const
    {
        return cancel_;
    }
};

template <class F>
class scope_guard_functor : public scope_guard_functor_base {
    F f_;
public:
    scope_guard_functor(F f)
        : scope_guard_functor_base(), f_(f) {}
    
    virtual ~scope_guard_functor()
    {
        if (!is_cancel())
            f_();
    }
};

} // namespace detail

class scope_guard {
    detail::scope_guard_functor_base* f_;
public:
    template <class F>
    scope_guard(F f)
        : f_(new detail::scope_guard_functor<F>(f)) {}
    
    void cancel()
    {
        f_->cancel();
    }

    ~scope_guard()
    {
        delete f_;
    }

private:
    scope_guard();
    scope_guard(const scope_guard&);
    scope_guard& operator=(const scope_guard&);
};

} // namespace shand

#endif // SHAND_SCOPE_GUARD_INCLUDE


使い方

#include <iostream>
#include <shand/scope_guard.hpp>

using namespace std;
using namespace shand;

struct functor {
    void operator()() const
    {
        cout << "functor" << endl;
    }
};

void func()
{
    cout << "func" << endl;
}

int main()
{
    scope_guard guard1 = functor();
    scope_guard guard2 = func;
    
    cout << "いろいろ処理..." << endl;

    guard1.cancel();
} // func


C++0xではこんな感じで使えます

#include <iostream>
#include <shand/scope_guard.hpp>

using namespace std;
using namespace shand;

int main()
{
    int* p = new int(3);

    scope_guard guard = [&]{ if (p) delete p; };

    // いろいろ処理・・・

} // ここでdelete