Before/After クラス
デザインパターンの一つに Before/After パターンというのがあるらしくて、これは Before 処理をしたら After 処理を必ず行うように保証するパターンらしい。
Java ならこんな風に書ける
public void func() { hoge.before(); try { doSomething(); } finally { hoge.after(); } }
これなら doSomething で例外が発生しても必ず hoge.after が呼ばれる。
C++ ならこんな風になる。
void func() { hoge.before(); try { do_something(); } catch (...) { hoge.after(); throw; } hoge.after(); }
hoge.after を2箇所に書いているのが恐ろしくかっこ悪いのだけれども、finally 節が無いので仕方ない。
ただ、C++ の場合は例外が発生してもデストラクタは必ず呼ばれるので、必ずこういう処理を行うクラスは簡単に用意できる。
struct scoped_before_after { Hoge& hoge_; scoped_before_after(Hoge& hoge) : hoge_(hoge) { hoge_.before(); } ~scoped_before_after() { hoge_.after(); } }; void func() { scoped_before_after lock(hoge); do_something(); }
何度も使うようなパターンであればこれでいいんだけど、一度しか使わないような Before/After ならわざわざ作るのはめんどい。
だからといって同じ文を2度書くのは嫌なので、こんなクラスを作ってみた。
#include <boost/function.hpp> struct scoped_before_after { boost::function0<void> after_; scoped_before_after(const boost::function0<void>& after) : after_(after) { } scoped_before_after(const boost::function0<void>& before, const boost::function0<void>& after) : after_(after) { before(); } ~scoped_before_after() { after_(); } };
これはこんな風に使う。
#include <boost/lambda/lambda.hpp> #include "scoped_before_after.h" struct fuga { int value_ = 0; void func() { using namespace boost::lambda; scoped_before_after(var(value_) += 1, var(value_) -= 1); do_something(); } };
このように、特にクラス化する必要すら感じられない Before/After 処理を書く場合は使えるかもしれない。