明示的インスタンス化 (C++ のみ)

コンパイラーに、テンプレートから定義をいつ生成するのかを明示的に指示できます。 これは、明示的インスタンス生成 と呼ばれます。 明示的インスタンス生成には、明示的インスタンス生成宣言 および明示的インスタンス生成定義 という 2 つのフォームが含まれます。

C++11
注: IBM® は、C++11 (承認前は C++0x と呼ばれていました) の選択された機能をサポートしています。 IBM は、この標準の機能の開発および実装を継続します。 この言語レベルの実装は、IBM による標準の解釈に基づいています。 新しい C++11 標準ライブラリーのサポートを含め、すべての C++11 機能を IBM が実装し終えるまで、リリースごとに実装が変更される可能性があります。 IBM では、IBM による C++11 の新機能の実装に関し、ソース、バイナリー、リスト作成などのコンパイラー・インターフェースにおいて、以前のリリースとの互換性を維持するための試みは行いません。

明示的インスタンス生成宣言

C++11 標準では、明示的インスタンス生成宣言機能が導入されています。 この機能を使用すると、テンプレート特殊化またはそのメンバーの暗黙のインスタンス生成を抑制できます。 明示的インスタンス生成宣言を示すには、extern キーワードを使用します。 ここでの extern の使用法は、ストレージ・クラス指定子の場合とは異なります。

明示的インスタンス生成宣言の構文

構文図を読む構文図をスキップするexterntemplate template_declaration

テンプレートの明示的インスタンス生成定義が、他の変換単位で存在するか、または後から同じファイル内に存在する場合は、テンプレート特殊化に対して明示的インスタンス生成宣言を指定できます。 1 つの変換単位に明示的インスタンス生成定義が含まれる場合、他の変換単位は特殊化で複数回インスタンス生成を行うことなく、特殊化を使用できます。 次の例は、このコンセプトを示しています。

//sample1.h:
template<typename T, T val>
union A{
   T func();
};
extern template union A<int, 55>;

template<class T, T val>
T A<T,val>::func(void){
   return val;
}

//sampleA.C"
#include "sample1.h"

template union A<int,55>;

//sampleB.C:
#include "sample1.h"

int main(void){
   return A<int, 55>().func();
}

sampleB.C は、sampleA.CA&lt;int, 55>().func() の明示的インスタンス生成定義を使用します。

関数またはクラスの明示的インスタンス生成宣言が宣言されているが、プログラム内に対応する明示的インスタンス生成定義が存在しない場合、コンパイラーはエラー・メッセージを出します。 次の例を参照してください。

// sample2.C
template <typename T, T val>
struct A{
   virtual T func();
   virtual T bar();
}

extern template int A<int,55>::func();

template <class T, T val>
T A<T,val>::func(void){
   return val;
}

template <class T, T val>
T A<T,val>::bar(void){
   return val;
}

int main(void){
   return A<int,55>().bar();
}
明示的インスタンス生成宣言を使用する場合、以下の制約事項に注意してください。
  • 明示的インスタンス生成宣言では静的クラス・メンバーに命名できますが、静的関数には命名できません。これは、静的関数は他の変換単位では名前でアクセスできないためです。
  • クラスの明示的インスタンス生成宣言は、その各メンバーの明示的インスタンス生成宣言と等価ではありません。
C++11

明示的インスタンス生成定義

明示的インスタンス生成定義は、テンプレート特殊化またはそのメンバーの インスタンス生成です。

Explicit instantiation definition syntax

構文図を読む構文図をスキップするtemplatetemplate_declaration
以下に、明示的インスタンス生成定義の例を示します。
template<class T> class Array { void mf(); };
template class Array<char>;       /* explicit instantiation definition */
template void Array<int>::mf();   /* explicit instantiation definition */

template<class T> void sort(Array<T>& v) { }
template void sort(Array<char>&); /* explicit instantiation definition */

namespace N {
   template<class T> void f(T&) { }
}

template void N::f<int>(int&);
// The explicit instantiation definition is in namespace N.

int* p = 0;
template<class T> T g(T = &p);
template char g(char);           /* explicit instantiation definition */

template <class T> class X {
   private:
      T v(T arg) { return arg; };
};

template int X<int>::v(int);    /* explicit instantiation definition */

template<class T> T g(T val) { return val;}
template<class T> void Array<T>::mf() { }

テンプレートの明示的インスタンス生成定義は、テンプレートを定義した場所と同じ名前空間にあります。

アクセス検査規則は、明示的インスタンス生成定義の引数には適用されません。 明示的インスタンス生成定義のテンプレート引数には、private 型または private オブジェクトを使用できます。 この例では、メンバー関数が privateとして宣言されている場合でも、明示的インスタンス生成定義 template int X&lt;int>::v(int) が使用できます。

テンプレートのインスタンスを明示的に生成する場合、コンパイラーは、デフォルトの引数を使用しません。 この例では、デフォルトの引数が型 int のアドレスである場合でも、明示的インスタンス生成定義 template char g(char) を使用できます。

注: インラインまたはC++11constexprC++11指定子を関数テンプレートの明示的インスタンス生成またはクラス・テンプレートのメンバー関数で使用することはできません。
C++11 の開始

明示的インスタンス生成定義およびインライン名前空間定義

インライン名前空間定義は、最初に inline キーワードを使用する名前空間定義です。 インライン名前空間のメンバーは、エンクロージング名前空間のメンバーでもあるかのように、インスタンス生成または特殊化を明示的に実行できます。 詳しくは、 インライン名前空間定義 (C++11)を参照してください。

C++11 ends