Oracle Solaris Studio 12.2: C++ ユーザーズガイド

5.2 テンプレート定義

テンプレート定義は 2 通りの方法で編成することができます。すなわち、テンプレート定義を取り込む方法 (定義取り込み型編成) と、分離する方法 (定義分離型編成) があります。テンプレート定義を取り込んだほうが、テンプレートのコンパイルを制御しやすくなります。

5.2.1 テンプレート定義の取り込み

テンプレートの宣言と定義を、そのテンプレートを使用するファイルの中に含める場合、編成が定義の取り込みです。次に例を示します。

main.cc


template <class Number> Number twice(Number original);
template <class Number> Number twice(Number original )
    { return original + original; }
int main()
    { return twice<int>(-3); }

テンプレートを使用するファイルに、テンプレートの宣言と定義の両方を含んだファイルをインクルードした場合も、定義取り込み型編成を使用したことになります。次に例を示します。

twice.h


#ifndef TWICE_H
#define TWICE_H
template <class Number>
Number twice(Number original);
template <class Number> Number twice( Number original )
    { return original + original; }
#endif

main.cc


#include “twice.h”
int main()
    { return twice(-3); }

注 –

テンプレートヘッダーをべき等にすることは非常に重要です。「5.1.2 べき等ヘッダーファイル」を参照してください。


5.2.2 テンプレート定義の分離

テンプレート定義を編成するもう一つの方法は、テンプレートの定義をテンプレート定義ファイルに記述することです。この例を次に示します。

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 オプションなしで定義すると、テンプレート定義ファイルが複数含められるためにコンパイルエラーが発生することがあります。