Singletonをテンプレート化する
今回はSingletonクラスをテンプレート化して簡単に定義できるようにしてみたいと思います。
#include <iostream> using namespace std; template<class T> class Singleton { private: class Auto { public: T* m_instance; Auto() : m_instance(0){} ~Auto() { cout << "~Auto" << endl; if ( m_instance ) { delete m_instance; m_instance = 0; } } }; static typename Singleton<T>::Auto m_auto; public: static T* getInstance() { if ( !m_auto.m_instance ) m_auto.m_instance = new T; return m_auto.m_instance; } }; template<class T> typename Singleton<T>::Auto Singleton<T>::m_auto;
こんな感じのテンプレートクラスを用意します。
使い方は簡単。Singleton化したいクラスのコンストラクタとデストラクタをprivateにし、friendクラスで上記Singletonを定義するだけです。
class Foo { friend class Singleton<Foo>; private: Foo() { cout << "Foo" << endl; }; ~Foo() { cout << "~Foo" << endl; }; }; int main () { Foo* foo = Singleton<Foo>::getInstance(); return 0; }
$ main Foo ~Auto ~Foo
また、継承して扱うことも出来ます。
// Singleton<Foo>を継承する class Foo : public Singleton<Foo> { friend class Singleton<Foo>; private: Foo() { cout << "Foo" << endl; }; ~Foo() { cout << "~Foo" << endl; }; }; int main () { // 継承しているのでFoo::getInstance()でポインタが取れる Foo* foo = Foo::getInstance(); return 0; }
またauto_ptrを使って実装した場合は、Fooクラスにauto_ptrのfriendクラス登録が必要になります。
class Foo { friend class Singleton<Foo>; friend class auto_ptr<Foo>; private: Foo() { cout << "Foo" << endl; }; ~Foo() { cout << "~Foo" << endl; }; };
とまぁこんな感じで。