2011-10-20 8 views
1

私は現在、次のような単純なシングルトンクラスを使用しています:シングルトンのテンプレートデザインの問題

template<class T> 
class singleton 
    : boost::noncopyable 
{ 
public: 
    static T& get_instance() 
     { 
      assert(sm_instance != nullptr); 
      return *static_cast<T*>(sm_instance); 
     } 

protected: 
    singleton() 
     { 
      assert(sm_instance == nullptr); 
      sm_instance = this; 
     } 
    virtual ~singleton() 
     { 
      assert(sm_instance != nullptr); 
      sm_instance = nullptr; 
     } 

private: 
    static singleton<T>* sm_instance; 
}; 

template<class T> singleton<T>* singleton<T>::sm_instance = nullptr; 


class example_one 
    : public singleton<example_one> 
{ 
    static example_one instance; 
}; 

example_one example_one::instance; 


class example_two 
    : singleton<example_two> 
{ 
    static example_two instance; 
}; 

example_two example_two::instance; 


// Usage: 
example_one& x = example_one::get_instance(); 
example_two& y = example_two::get_instance(); // not accessible because 'example_two' uses 'private' to inherit from 'singleton<T>' 

しかし、私はいくつかのことを微調整したいと思います。私はget_instance()が派生クラスに継承されているのは好きではありません。

私はこの(非動作するコード)のような何かをしたいと思います:あなたは、なぜ、基本クラスを気にテンプレート機能を使用しようとしている場合は

template<class T> 
T& get_singleton(); 

template<class T> 
class singleton 
{ 
    friend T& get_singleton() 
     { 
      assert(sm_instance != nullptr); 
      return *static_cast<T*>(sm_instance); 
     } 
} 

// Usage: 
example_two& x = get_singleton<example_two>(); 
+0

あなたがシングルトンを使用していない、どのような方法でそれを避けることができれば - http://stackoverflow.com/questions/1392315/problems-with-singleton-pattern –

+0

あなたのコードがない可能多くのセンス。最初の例では、そのインスタンスフィールドがnullかどうか、コンストラクタで(なぜ?)、そしてデストラクタがさらに悪いかどうかを調べます。デストラクタはsm_instanceを削除するか、デストラクタをまったく必要としません。また、デストラクタの内部にinstacneフィールドをnullに設定することは、全く無意味です。 –

+0

@ AngelO'Sphere - もう一度コードを読んで考えてください。 – 0xbadf00d

答えて

0

を:

template<typename T> 
T& getInstance() 
{ 
    static T instance; 
    return instance; 
} 

class example_one: boost::noncopyable 
{ 
     example_one() {} // Note private construtor 
     friend example_one& getInstance<example_one>(); 
}; 

class example_two: boost::noncopyable 
{ 
     example_two() {} 
     friend example_two& getInstance<example_two>(); 
}; 
+0

これは私のアプローチより柔軟性がありません。 'friend'宣言、プライベートコピーコンストラクタと代入演算子が必要で、' class'コンストラクタにコンパイル時定数を渡せません。 – 0xbadf00d

+0

いいえ私はこれをやっていません(私のコードでsingeltonsを見つけるつもりはないので)。しかし、あなたの議論には全て欠陥があります。 1)コンストラクタに何も渡す必要がないシングルトンだけが存在するため、コンストラクタで何も渡す必要はありません。 2)プライベートコンストラクタ/コピーコンストラクタと代入演算子がすべてのシングルトンに必要です。 3)私のクラスは友人と1行の余分なコードを持っています。不必要なボイラープレートのサブクラスを定義しました。私はあなたが私のきれいな、より保守的なものを見つけるだろうと思う。たとえシングルトンが最初から完全に悪い考えであったとしても。 –

+0

もし私がシングルトンを作るつもりなら、私は古典的なMyers Singletonを使います。ボイラープレートを一般化しようとしていたので、私はこのようにしました。 –

0

Andrei Alexandrescuによって普及された解決策は、これと比較していくつかの利点を持つ異なるテクニックを使用しています(そのうちの1つは、作成したい調整です)。 http://loki-lib.cvs.sourceforge.net/loki-lib/loki/include/loki/Singleton.h?view=markupで入手できますが、ライブラリ全体(loki)をダウンロードしたい場合や、追加情報が不要な場合は少し削除してください。インタフェースは、次のようになります。

typedef Loki::SingletonHolder< SomeType > SomeTypeSingleton; 
SomeTypeSingleton::Instance(); // Access the single instance 
関連する問題