template library を作る - Singleton

since: 2001-12-?? update: 2001-12-?? count:

コード - singleton.h

template<class _T>
class Singleton {
public:
    static _T* instance();
    Singleton();
    virtual ~Singleton();

protected:
    static Singleton* _instance;
};

template<class _T>
_T* Singleton<_T>::instance() {
    if (_instance == 0) {
    _instance = new _T;
    }
    return dynamic_cast<_T*>(_instance);
}

template<class _T>
Singleton<_T>* Singleton<_T>::_instance = 0;

template<class _T>
Singleton<_T>::Singleton() {
    assert(_instance == 0);
    _instance = this;
}

template<class _T>
Singleton<_T>::~Singleton() {
}

使い方 - singletonTest.cc

class ConcreteSingleton : public Singleton<ConcreteSingleton> {
};

int main() {
    ConcreteSingleton* cs1 = ConcreteSingleton::instance();
    ConcreteSingleton* cs2 = ConcreteSingleton::instance();
    assert(cs1 != 0);
    assert(cs1 == cs2);
}

説明

いきなり結構有名な例で恐縮ですが。

OO の技法にデザインパターンというものがあり、 その中に Singleton と呼ばれるパターンがあることは ご存じ…なんだろうか? 簡単に説明すると、

class Hoge {
public:
    static Hoge* getInstance() {
        if (_instance == 0) {
        _instance = new Hoge;
    }
        return _instance;
    }
protected:
    Hoge();
private:
    static Hoge* _instance;
};

Hoge* Hoge::_instance = 0;

として、このクラスはいつでもどこでも

Hoge* hoge = Hoge::getInstance();

で入手できることと、それが一つであることを保証するというものです。 まあ高級なグローバル変数だと思えば良いと思います。 詳しい説明は Singleton で google したら山程出てくると思います。

で Singleton が何かと言いますと、これを毎回 Singleton にしたいクラスに 書くのはかなり面倒な単純作業なのです。 イメージとしては Singleton 基底クラスを作って、 それを継承すればいいんじゃ…とわかるのですが、 これが例えば普通にはできません。 何故なら Singleton 基底クラスは、 派生クラスのクラス名を _instance の型として知らなければならないからです。 そこで template 引数として派生クラスが自分のクラス名を Singleton 基底クラスに教えてやる、と、 口で言うと簡単なんですがコードで書くと慣れない内は びっくりするものができあがります。

使用例は非常に短いですが、実際これで ConcreteSingleton は立派な Singleton として機能します。 ただ残念なのは ConcreteSingleton はコンストラクタが public なので自分で作られてしまってもコンパイラは検出できません。 ま、一応実行時に assert が出るので大丈夫だと思いますが。

Java はこれができない…


home / index

全てリンクフリーです。 コード片は自由に使用していただいて構いません。 その他のものはGPL扱いであればあらゆる使用に関して文句は言いません。 なにかあれば下記メールアドレスへ。

shinichiro.hamaji _at_ gmail.com / shinichiro.h