たぶん究極のC++ライブラリ、Lokiを使う - Singleton

since: 2002-02-21 update: 2002-02-21 count: 23137

まだ簡単な方です、お馴染シングルトン。

基本的な使い方を示します。

class Class {};
typedef Loki::SingletonHolder<Class> ClassHolder;

で定義終了。使い方は、

Class& c = ClassHolder::Instance();

でどんなところからでも一つのオブジェクトを参照できる、と。

次はデフォルトコンストラクタが無い場合です。 この Singleton はオブジェクトの生成法を テンプレート第二引数によってポリシーとして渡すことができます。 このポリシークラスは static なメンバ関数 Create と Destroy を 用意する必要があります。つまり、

class Class2 {
public:
  explicit Class2(int);
};

なんていうデフォルトコンストラクタが無いクラスをシングルトンにしたければ、

template<class T>
class Class2Creater {
public:
  static T* Create() {
    return new Class2(0);
  }
  static void Destroy(T* c) {
    delete c;
  }
};

というような自作ポリシークラスを用意して、

typedef Loki::SingletonHolder<Class, Class2Creater> ClassHolder;

と、テンプレート第二引数でポリシーを渡してやれば OK です。

ここまでのサンプルコード

次は寿命管理の話なんですが、 どう考えてもマニアック過ぎて実用的には見えないです。 シングルトンのデストラクタが他のシングルトンを欲しがる場合、 それが既に破壊されていたらどうするんだ、という話ですが、 そんなときってありますかねえ?

ま、簡単に説明すると、Lokiでは二つのアプローチが示されています。 一つは破壊されたシングルトンが必要になったらもう一度生成する、 通称、フェニックスシングルトン。 もう一つは完全に破壊される順序を自分で定義できる (けど少しめんどくさい)アプローチ。

前者は

typedef Loki::SingletonHolder<Class,
    Loki::CreateUsingNew, Loki::PhoenixSingleton> ClassHolder;

で終わり。後者は、

inline unsigned int GetLongevity(Class*) { return 1; }
typedef Loki::SingletonHolder<Class,
    Loki::CreateUsingNew, Loki::SingletonWithLongevity> ClassHolder;

と unsigned int GetLongevity(Class*) なる関数がミソ。 このポリシーがインスタンシエイトされるときに この関数がスコープ内にある必要があります。 これの帰り値が多いものほど後で壊れる、 って書いてあるんですけど私の環境では逆になるんですけど。謎。

フェニックスシングルトンのサンプルコード
ユーザ制御シングルトンのサンプルコード

細かい注意として #define ATEXIT_FIXED しないと、 うまく破壊されない、ってことと、 ユーザ制御シングルトンは loki/Singleton.cpp を コンパイルしたオブジェクトをリンクしなきゃ リンクエラーがでてしまう、ってことがあります。


home / index

全てリンクフリーです。 コード片は自由に使用していただいて構いません。 その他のものはGPL扱いであればあらゆる使用に関して文句は言いません。 なにかあれば下記メールアドレスへ。

shinichiro.hamaji _at_ gmail.com / shinichiro.h