boost::shared_ptrのdelete

昨日、boost::shared_ptrの実装を調べてみた。何に注目していたのかというと、boost::shared_ptrではデストラクタを自動的に選んでくれる点。boost::shared_ptrであっても中に入れたクラスのdeleteを呼んでくれるというのが不思議だった。
答え:初期化時に貰ったポインタの型を元に生成されたテンプレート・クラスが内部に存在する。
私はデストラクタのポインタを初期化時に取得するのかと思っていたが、boost::shared_ptrはもっと頭の良い方法だった。確かにboost::shared_ptr()の引数として受け取った時点では真の型を持っているのだからそれを使うのが賢い。勉強になった。
C++のテンプレートでは、

class Base {
}
template<typename T>
class Sub : public Base {
private:
  T* ptgt;
public:
  Sub<T>(T* _ptgt):
    ptgt(_ptgt) {
  }
}

と定義されている場合に

int main() {
  Base* pb = new Sub(new int(1));
  return 0;
}

とすることは出来ない。C++の文法上、先に型が確定していないとコンストラクタが呼べないからだ。これはファクトリ・メソッドで

template<typename T>
Base* create(T* _ptgt) {
  return new Sub<T>(_ptgt);
}
int main() {
  Base* pb = create(new int(1));
  return 0;
}

とすると静的に型を解決できる。
まとめ:スマートポインタでは、外から見た型と中から見た型を分けて扱う、中から見た型を自動的に決定する、中から見た型を隠蔽する、という要望がある。テンプレート・クラスでこれを解決する場合には、外から見た型を表すクラスと中から見た型を表すクラスの二重構造にする。また中から見た型を自動的に決定するにはファクトリ・メソッドを使う。