http://d.hatena.ne.jp/nagoya313/20090930/1254321172を拝見して。
これは「『奇妙に再帰したテンプレートパターン』を使うと簡単にできなかったっけ?」と、記憶をたどりながらコードを書いてみた。
#include <iostream> template<typename T> class Singleton { public: static T& getInstance() { static T instance; return instance; } protected: Singleton() {} private: Singleton(const Singleton&); Singleton& operator = (const Singleton&); };
使う。
class Foo : public Singleton<Foo> { public: void set(int n) { n_ = n; } int get() const { return n_; } private: friend class Singleton<Foo>; Foo() : Singleton<Foo>() {} // ※1 int n_; }; int main(int, char* []) { Foo& foo1 = Foo::getInstance(); std::cout << "foo1.get() = " << foo1.get() << std::endl; foo1.set(10); std::cout << "foo1.get() = " << foo1.get() << std::endl; Foo& foo2 = Foo::getInstance(); std::cout << "foo2.get() = " << foo2.get() << std::endl; // Foo foo3; // ERROR コンストラクタは非公開 // Foo foo3(foo1); // ERROR コピーコンストラクタは非公開 // foo3 = foo1; // そもそも別のインスタンスを作れないからありえないのだけれど、 // 代入演算子も非公開 return 0; }
(厳密にはこれだけだとオブジェクトの生成/破棄のタイミングで問題になることがあるのだけれど、そこは見なかったことにする)
しかし、派生クラスでコンストラクタを非公開にしないとならない(※1の場所)はどうにもならないんだっけか?なにか手があったような気がしたのだけれど、思い出せない。
加えてSingleton
からT
のコンストラクタは見えないといけないので、friendクラスにする必要がある。
結局スマートじゃないなー。なんか納得いかない。