テンプレート定義を編成するもう一つの方法は、テンプレートの定義をテンプレート定義ファイルに記述することです。この例を次に示します。
twice.h
#ifndef TWICE_H #define TWICE_H template <class Number> Number twice(Number original); #endif TWICE_H |
twice.cc
template <class Number> Number twice( Number original ) { return original + original; } |
main.cc
#include “twice.h” int main( ) { return twice<int>( -3 ); } |
テンプレート定義ファイルには、べき等ではないヘッダーファイルをインクルードしてはいけません。また、通常はテンプレート定義ファイルにヘッダーファイルをインクルードする必要はありません。「5.1.2 べき等ヘッダーファイル」を参照してください。なお、テンプレートの定義分離型編成は、すべてのコンパイラでサポートされているわけではありません。
独立した定義ファイルはヘッダーファイルなので、多数のファイルに暗黙のうちにインクルードされることがあります。そのため、テンプレート定義の一部でないかぎり、あらゆる関数と変数はこのファイルに含めないようにします。独立した定義ファイルには、typedef などの型定義を定義できます。
通常、テンプレート定義ファイルには、ソースファイルの拡張子 (.c、.C、.cc、.cpp、.cxx、.c++ のいずれか) を付けますが、このテンプレート定義ファイルはヘッダーファイルです。コンパイラは、これらのファイルを必要に応じて自動的に取り込みます。テンプレート定義ファイルの単独コンパイルは行わないでください。
このように、テンプレートの宣言と定義を別々のファイルで指定した場合は、定義ファイルの内容、その名前、配置先に特に注意する必要があります。さらに、定義ファイルの配置先をコンパイラに明示的に通知する必要もあります。テンプレート定義の検索規則については、「7.5 テンプレート定義の検索」を参照してください。
-E オプションまたは -P オプションを使用してプリプロセッサ出力を生成する場合、定義分離ファイルの構成では、テンプレート定義を .i ファイルに含めることが許可されません。見つからない定義があるため、.i ファイルのコンパイルに失敗します。テンプレート定義ファイルをテンプレート宣言ヘッダー (次のコード例を参照) に条件付きで含めることで、コマンド行で -template=no%extdef を使用することによりテンプレート定義を使用できます。libCtd ライブラリと STLport ライブラリは、この方法で実装されます。
// templace declaration file template <class T> class foo { ... }; #ifdef _TEMPLATE_NO_EXTDEF #include "foo.cc" //template definition file #endif |
ただし、マクロ _TEMPLATE_NO_EXTDEF を自分で定義しないでください。—template=no%extdef オプションなしで定義すると、テンプレート定義ファイルが複数含められるためにコンパイルエラーが発生することがあります。