あめだまふぁくとりー

Boost.Graphとかできますん

Boost.Function を使わない SCOPE_EXIT_ALL

修正(2015-02-22) RVO を無効化した場合, 指定した処理が複数回実行されてしまうのを修正しました.

Boost.Scope Exit の実装を覗いてみたら, C++11 (or later) 用の BOOST_SCOPE_EXIT_ALL には Boost.Function が使用されていました. Boost.Function は動的メモリの確保を必要とすると思うので, 使わないでいい方法を考えてみました.

#include <iostream>
#include <utility>

template <class F>
struct guard
{
    explicit guard(F&& f) : f_(std::forward<F>(f)), callable_(true) {}
    guard(guard&& other)
        : f_(std::forward<F>(other.f_)), callable_(true)
    {
        other.callable_ = false;
    }
    ~guard() {
        if (callable_) f_();
    }
private:
    F f_;
    bool callable_;
};

namespace detail {
    struct guard_gen
    {
        template <class F>
        auto operator=(F&& f) const -> guard<F>
        {
            return guard<F>{std::forward<F>(f)};
        }
    };
} // namespace detail

// 変数名とかキャプチャの処理はここでは省略する
#define SCOPE_EXIT_ALL() \
    auto scope_exit = detail::guard_gen{} = []()

int main(int argc, char const* argv[])
{
    {
        SCOPE_EXIT_ALL() {
            std::cout << "exit" << std::endl;
        };
        std::cout << "start" << std::endl;
    }
    return 0;
}

実行結果

start
exit