テンプレートの特殊化が明示的にインスタンス化されない限り、
または明示的に特殊化されない限り、コンパイラーは、定義が必要とされる場合にのみ、
テンプレートの特殊化を生成します。
これは、暗黙のインスタンス化 と呼ばれます。
コンパイラーが、クラス・テンプレート特殊化のインスタンスを生成する必要があり、 テンプレートが宣言される場合、テンプレートも定義する必要があります。
例えば、クラスを指すポインターを宣言する場合、そのクラスの定義は、必要とされず、 そのクラスは、暗黙的にインスタンス作成されません。 次は、コンパイラーが、テンプレート・クラスのインスタンスを作成する例を示しています。
template<class T> class X { public: X* p; void f(); void g(); }; X<int>* q; X<int> r; X<float>* s; r.f(); s->g();
コンパイラーは、次のクラスおよび関数のインスタンス化を必要とします。
したがって、上記の例をコンパイルするには、 関数 X<T>::f() および X<T>::g() を定義する必要があります。 (コンパイラーは、オブジェクト r を作成する場合、 クラス X のデフォルトのコンストラクターを使用します。) コンパイラーは、次の定義のインスタンス化を必要としません。
コンパイラーが、ポインター型変換、またはメンバー型変換を指すポインターに関係する場合、 それはクラス・テンプレート特殊化のインスタンスを暗黙的に生成します。 次の例は、このことを示しています。
template<class T> class B { }; template<class T> class D : public B<T> { }; void g(D<double>* p, D<int>* q) { B<double>* r = p; delete q; }
代入 B<double>* r = p は、型 D<double>* の p を B<double>* の型に変換します。コンパイラーは、D<double> のインスタンスを生成する必要があります。コンパイラーは、q の削除を試みる際に、 D<int> のインスタンスを生成しなければなりません。
コンパイラーが、静的メンバーを含むクラス・テンプレートのインスタンスを暗黙的に生成する場合、 それらの静的メンバーのインスタンスは、暗黙的には生成されません。 コンパイラーは、静的メンバーの定義を必要とする場合のみ、 静的メンバーのインスタンスを生成します。 インスタンスを生成されたクラス・テンプレートは、どれも静的メンバーの自分用のコピーを所有しています。 次の例は、このことを示しています。
template<class T> class X { public: static T v; }; template<class T> T X<T>::v = 0; X<char*> a; X<float> b; X<float> c;
オブジェクト a には、型 char* の静的メンバー変数 v があります。 オブジェクト b には、型 float の静的変数 v があります。 オブジェクト b と c は、単一静的データ・メンバー v を共用します。
暗黙的にインスタンスを生成されたテンプレートは、 テンプレートを定義した場所と同じネーム・スペースにあります。
関数テンプレート、またはメンバー関数テンプレート特殊化が、 多重定義解決にかかわってくる場合、コンパイラーは、 特殊化の宣言のインスタンスを暗黙的に生成します。
関連参照