CRTP (奇妙に再帰したテンプレートパターン)  を使ったシングルトン

[CRTP](https://ja.wikibooks.org/wiki/More_C%2B%2B_Idioms/%E5%A5%87%E5%A6%99%E3%81%AB%E5%86%8D%E5%B8%B0%E3%81%97%E3%81%9F%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%28Curiously_Recurring_Template_Pattern%29) (奇妙に再帰したテンプレートパターン) を使ったシングルトンポリシークラスを作って使い回したいと色々試行錯誤した結果、最終的に [StackOverflow のこの記事](http://stackoverflow.com/questions/24964769/singletons-curiously-recurring-template-pattern-and-forwarding-constructor-para) に行き着いた。

ここでは前述の記事から機能を抜いた劣化版（？）のシングルトンクラスを紹介します。

# シングルトンクラスの要件

こんな感じのクラスを作りたいというのが発端です。

1. インスタンス取得に仮想関数を使わない
2. 最初に呼ばれるまでメモリを占有しない
3. プログラム終了時にデストラクタが呼ばれる
4. 使い回せてコーディングが楽

# 最終的なコード

```cpp:singleton.hpp
template<typename T>
class Singleton
{
public:
    //! シングルトンのインスタンスを取得
    static T& getInstance()
    {
        // 最初に呼ばれたときに一度だけ初期化される
        static T singleton; 
        return singleton;
    }
    
protected:
    Singleton() = default;
    virtual ~Singleton() = default;
    
    // コピー・代入禁止
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};
```

# 最低限の使い方

最低限のコードはクラス定義に Singleton クラス継承を足しただけのシンプルなものです。

```cpp
class Foo : public Singleton<Foo>
{
};
```

継承元である `Singleton` クラスのテンプレート引数に自分自身 (Foo) を入れているのが CRTP イディオム特有のところです。
見慣れないと奇妙な感じですが使用例を見てみましょう。

## 使用例1

```cpp:sample1.cpp
#include <iostream>
#include "singleton.hpp"
using namespace std;

class Foo : public Singleton<Foo>
{
public:
  void bar() {
      cout << "シングルトンだよ\n";
  }
};

int main(void)
{
    cout << "*** CHECK POINT 1 ***\n";
    
    Foo& foo = Foo::getInstance();
    foo.bar();
    
    cout << "*** CHECK POINT 2 ***\n";
    
}
```

```txt:出力
*** CHECK POINT 1 ***
シングルトンだよ
*** CHECK POINT 2 ***
```

`Foo::getInstance()` を呼ぶと `Singleton` クラスの `static T& getInstance()` が呼ばれますが、ここでテンプレート引数 `T` に `Foo` が渡されているため `Foo&` が返ってきます。それで `Foo` のメンバ関数 `bar()` が使えています。
ここが CRTP のミソの部分で、「インスタンス取得に仮想関数を使わない」という要件が満たされています。

基本的な使用法これだけなのですが、 `Foo` にプライベートのコンストラクタやデストラクタを持たせたいときにはもうひと作業必要です。

# private コンストラクタ・デストラクタを使用する最低限のコード

継承先のクラスで `Singleton` をフレンドクラスに登録してあげる必要があります。

```cpp
class Foo : public Singleton<Foo>
{
  friend class Singleton;

  Foo() { /* 実装 */ }
  ~Foo() { /* 実装 */ }
};
```

`Singleton::getInstance` 内で `Foo` のインスタンスを生成しているため、 `Singleton` クラスが `Foo` のコンストラクタ・デストラクタにアクセスできるようにしてあげるためです。

## 使用例2

private コンストラクタ・デストラクタの使用例です。

```cpp:sample2.cpp
#include <iostream>
#include "singleton.hpp"
using namespace std;

class Foo : public Singleton<Foo>
{
public:
  
  void bar() {
      cout << "シングルトンだよ\n";
  }
  
private:
  friend class Singleton;

  Foo() {
      cout << "生まれたよ\n";
  }
  
  ~Foo() {
      cout << "死んだよ\n";
  }
};

int main(void)
{
    cout << "*** CHECK POINT 1 ***\n";
    
    Foo& foo = Foo::getInstance();
    foo.bar();
    
    cout << "*** CHECK POINT 2 ***\n";
    
}
```

```txt:出力
*** CHECK POINT 1 ***
生まれたよ
シングルトンだよ
*** CHECK POINT 2 ***
死んだよ
```

出力を見ると CHECK POINT 1 より後にコンストラクタが呼ばれているのが分かります。【シングルトンクラスの要件】に挙げた、「2. 最初に呼ばれるまでメモリを占有しない」が満たされています。
「3. プログラム終了時にデストラクタが呼ばれる」のも確認できます。

なかなか便利ではないでしょうか。

# 補足

冒頭に挙げた [StackOverflow の記事](http://stackoverflow.com/questions/24964769/singletons-curiously-recurring-template-pattern-and-forwarding-constructor-para) では、この記事で紹介した機能に加え、最初の `getInstance` 使用時にパラメータを渡し、引数付きコンストラクタを呼べるようにしてあります。そちらもご参考ください。