エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

Singleton Template

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クラスにする必要がある。

結局スマートじゃないなー。なんか納得いかない。