Content-Length: 78170 | pFad | https://melpon.hatenadiary.org/entry/20080104/p1

Before/After クラス - melpon日記 - HaskellもC++もまともに扱えないへたれのページ

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 処理を書く場合は使えるかもしれない。









ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: https://melpon.hatenadiary.org/entry/20080104/p1

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy