明示的インスタンス化 (C++ のみ)
コンパイラーに、テンプレートから定義をいつ生成するのかを明示的に指示できます。 これは、明示的インスタンス生成 と呼ばれます。 明示的インスタンス生成には、明示的インスタンス生成宣言 および明示的インスタンス生成定義 という 2 つのフォームが含まれます。
![C++11](ngcpp11_begin.gif)
明示的インスタンス生成宣言
extern
キーワードを使用します。 ここでの extern
の使用法は、ストレージ・クラス指定子の場合とは異なります。
テンプレートの明示的インスタンス生成定義が、他の変換単位で存在するか、または後から同じファイル内に存在する場合は、テンプレート特殊化に対して明示的インスタンス生成宣言を指定できます。 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.C
で A<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](ngcpp11_end.gif)
明示的インスタンス生成定義
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<int>::v(int)
が使用できます。
テンプレートのインスタンスを明示的に生成する場合、コンパイラーは、デフォルトの引数を使用しません。 この例では、デフォルトの引数が型 int
のアドレスである場合でも、明示的インスタンス生成定義 template char g(char)
を使用できます。
インライン
または![C++11](ngcpp11_begin.gif)
constexpr
![C++11](ngcpp11_end.gif)
![C++11 の開始](ngcpp11_begin.gif)
明示的インスタンス生成定義およびインライン名前空間定義
インライン名前空間定義は、最初に inline
キーワードを使用する名前空間定義です。
インライン名前空間のメンバーは、エンクロージング名前空間のメンバーでもあるかのように、インスタンス生成または特殊化を明示的に実行できます。 詳しくは、 インライン名前空間定義 (C++11)を参照してください。
![C++11 ends](ngcpp11_end.gif)