さて、中途半端なところで前回(id:wata_d:20050722:1122031393)は終わってしまいましたが、今回はその微妙な続きです。
前回の SingletonHolderではそれを適用するユーザ定義クラスの方でも、コンストラクタをプライベートにするなど多少やらなければならない作業が残ってしまいました。今回はその残り物も片付けるために、template library を作る - Singleton(Entangled Space)にあるshinichiro.hさん(id:shinichiro_h)のコードを参考にして、次のようなクラスを作ってみました。参考にしたというかパクりですごめんなさい。ところでこちらの公開されているソースだけを見ると、 _instance メンバが delete されていないように見えるのですがどこか見落としがあるのでしょうか。派生クラス側で delete するべきものなのかな。
template<class T> class SingletonTmpl { public: static T& Instance() { static T theInstance; return theInstance; } private: SingletonTmpl() {} SingletonTmpl(const SingletonTmpl&); SingletonTmpl& operator=(const SingletonTmpl&); friend T; // コンストラクタがprivateだと導出したクラスの生成ができないのでfriendにする }; //! ユーザ定義クラス class Hage : public SingletonTmpl<Hage> { /*...いろいろ実装...*/ };
基底クラスのテンプレート引数に派生クラスを渡す手法は WTL で使われていてその筋では有名なものですが、この手法では他にも virtual を使用せずに、仮想関数と同等のことが実現できたりもします。それはさておき、この方法を使えば SignletonTmpl を継承するだけでそれ以外の Singleton を実装するために必要な作業を全て省くことができます。継承を使っているところが気にならなくも無いですが、継承すら使用せずにこれを実現させるにはマクロを使うくらいしかもう思いつきませんでした。よりクールでエレガントな実装は果たして存在するのか、あれば見てみたいものです。
なお今回もコンストラクタに引数がある場合などに対応していません。近いうちに「ポリシー」まで進めて、この辺りに対応してみたいと思います。――予告までしてしまったが、果たしてここまで読んでいる人がいるのだろうか……。まあ、自分での確認みたいなものなので、読み手の有無はどうでもいいんですが。もちろんインターネット上に公開している以上、誰かが読む事も意識しながら書いてはいますけどね。