図1:関数テンプレート
テンプレートヘッダー.h
template<typename T>
void f();
テンプレートCpp.cpp
template<typename T>
void f(){
//...
}
//explicit instantation
template void f<T>();
メイン.cpp
#include "TemplHeader.h"
extern template void f<T>(); //is this correct?
int main() {
f<char>();
return 0;
}
これは正しい使用方法でしょうかextern template
、それとも図 2 のようにクラス テンプレートにのみこのキーワードを使用するのでしょうか?
図2:クラステンプレート
テンプレートヘッダー.h
template<typename T>
class foo {
T f();
};
テンプレートCpp.cpp
template<typename T>
void foo<T>::f() {
//...
}
//explicit instantation
template class foo<int>;
メイン.cpp
#include "TemplHeader.h"
extern template class foo<int>();
int main() {
foo<int> test;
return 0;
}
これらすべてを 1 つのヘッダー ファイルに入れるのが良いことはわかっていますが、複数のファイルで同じパラメーターを持つテンプレートをインスタンス化すると、同じ定義が複数作成され、コンパイラーはエラーを回避するためにそれらをすべて (1 つを除く) 削除します。 はどのように使用すればよいですかextern template
? クラスにのみ使用できますか、それとも関数にも使用できますか?
また、図 1 と図 2 は、テンプレートが 1 つのヘッダー ファイルにあるソリューションに拡張される可能性があります。その場合、extern template
複数の同じインスタンス化を回避するために、キーワードを使用する必要があります。これはクラスまたは関数にのみ適用されますか?
ベストアンサー1
extern template
コンパイラに強制的に実行させる場合にのみ使用してください。ないテンプレートをインスタンス化するあなたが知っている別の場所でインスタンス化されることを意味します。これは、コンパイル時間とオブジェクト ファイルのサイズを削減するために使用されます。
例えば:
// header.h
template<typename T>
void ReallyBigFunction()
{
// Body
}
// source1.cpp
#include "header.h"
void something1()
{
ReallyBigFunction<int>();
}
// source2.cpp
#include "header.h"
void something2()
{
ReallyBigFunction<int>();
}
これにより、次のオブジェクト ファイルが生成されます。
source1.o
void something1()
void ReallyBigFunction<int>() // Compiled first time
source2.o
void something2()
void ReallyBigFunction<int>() // Compiled second time
両方のファイルがリンクされている場合、一方void ReallyBigFunction<int>()
が破棄され、コンパイル時間とオブジェクト ファイルのサイズが無駄になります。
extern
コンパイル時間とオブジェクトファイルのサイズを無駄にしないために、テンプレート関数をコンパイルしないようにするキーワードがあります。これを使用してください。あなたが知っている場合のみ同じバイナリのどこか他の場所で使用されます。
変更source2.cpp
後:
// source2.cpp
#include "header.h"
extern template void ReallyBigFunction<int>();
void something2()
{
ReallyBigFunction<int>();
}
次のオブジェクト ファイルが生成されます。
source1.o
void something1()
void ReallyBigFunction<int>() // compiled just one time
source2.o
void something2()
// No ReallyBigFunction<int> here because of the extern
これら両方がリンクされると、2 番目のオブジェクト ファイルは最初のオブジェクト ファイルのシンボルを使用するだけです。破棄する必要がなく、コンパイル時間とオブジェクト ファイル サイズの無駄も発生しません。
これはプロジェクト内でのみ使用する必要があります。たとえば、テンプレートを複数回使用する場合は、 1 つのソース ファイルを除くすべてのソース ファイルでvector<int>
使用する必要があります。extern
これは、クラスと関数、さらにはテンプレート メンバー関数にも適用されます。