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() { }
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 はこれができない…
全てリンクフリーです。 コード片は自由に使用していただいて構いません。 その他のものはGPL扱いであればあらゆる使用に関して文句は言いません。 なにかあれば下記メールアドレスへ。