Class template
クラステンプレートはクラスのファミリーを定義します。
目次 |
構文
template
<
parameter-list
>
class-declaration
|
(1) | ||||||||
template
<
parameter-list
>
requires
constraint
class-declaration
|
(2) | (C++20以降) | |||||||
export
template
<
parameter-list
>
class-declaration
|
(3) | (C++11で削除) | |||||||
説明
| class-declaration | - | クラス宣言 。宣言されたクラス名はテンプレート名となる。 |
| parameter-list | - | 空でないカンマ区切りの テンプレートパラメータ のリスト。各パラメータは 定数パラメータ 、 型パラメータ 、 テンプレートパラメータ 、またはこれらのいずれかの パラメータパック である。 |
| constraint | - | このクラステンプレートが受け入れるテンプレートパラメータを制限する 制約式 |
export
はオプションの修飾子であり、テンプレートを
エクスポート済み
として宣言する(クラステンプレートと共に使用する場合、そのすべてのメンバーもエクスポート済みとして宣言される)。エクスポートされたテンプレートをインスタンス化するファイルは、その定義を含める必要がなかった:宣言のみで十分であった。
export
の実装は稀であり、詳細について実装間で意見が一致していなかった。
|
(C++11まで) |
クラステンプレートのインスタンス化
クラステンプレート自体は、型、オブジェクト、またはその他の実体ではありません。テンプレート定義のみを含むソースファイルからはコードは生成されません。コードを生成するためには、テンプレートをインスタンス化する必要があります:コンパイラが実際のクラス(または関数テンプレートからの関数)を生成できるように、テンプレート引数を指定する必要があります。
明示的インスタンス化
template
class-key
template-name
<
argument-list
>
;
|
(1) | ||||||||
extern
template
class-key
template-name
<
argument-list
>
;
|
(2) | (C++11以降) | |||||||
| class-key | - |
class
,
struct
または
union
|
明示的なインスタンス化定義は、それが参照するクラス、構造体、または共用体のインスタンス化を強制します。これはテンプレート定義の後であればプログラム内のどこにでも現れることができ、与えられた argument-list に対しては、プログラム全体で一度だけ現れることが許可され、診断は要求されません。
|
明示的インスタンス化宣言(extern template)は暗黙のインスタンス化ステップをスキップします:暗黙のインスタンス化を引き起こすコードは、代わりに他の場所で提供される明示的インスタンス化定義を使用します(そのようなインスタンス化が存在しない場合はリンクエラーが発生します)。これは、テンプレートを使用するソースファイルのうち1つを除くすべてのファイルで明示的にテンプレートインスタンス化を宣言し、残りのファイルで明示的に定義することで、コンパイル時間を短縮するために使用できます。 |
(C++11以降) |
クラス、関数 、変数 (C++14以降) 、およびメンバーテンプレートの特殊化は、それらのテンプレートから明示的にインスタンス化することができます。クラステンプレートのメンバー関数、メンバークラス、および静的データメンバーは、それらのメンバー定義から明示的にインスタンス化することができます。
明示的なインスタンス化は、修飾付きIDを使用しない限り、テンプレートの外側の名前空間内でのみ記述できます:
namespace N { template<class T> class Y // テンプレート定義 { void mf() {} }; } // template class Y<int>; // エラー: クラステンプレートYはグローバル名前空間で可視ではない using N::Y; // template class Y<int>; // エラー: テンプレートの名前空間外での明示的インスタンス化 // テンプレートの名前空間外での明示的インスタンス化 template class N::Y<char*>; // OK: 明示的インスタンス化 template void N::Y<double>::mf(); // OK: 明示的インスタンス化
明示的なインスタンス化は、同じテンプレート引数のセットに対して 明示的特殊化 が前に現れた場合には効果を持ちません。
関数テンプレート 、変数テンプレート (C++14以降) 、クラステンプレートのメンバ関数または静的データメンバ、あるいはメンバ関数テンプレートを明示的にインスタンス化する場合、宣言のみが可視である必要があります。クラステンプレート、クラステンプレートのメンバクラス、またはメンバクラステンプレートの明示的インスタンス化では、同じテンプレート引数を持つ明示的特殊化が以前に現れていない限り、完全な定義が明示的インスタンス化の前に現れなければなりません。
関数テンプレート 、変数テンプレート (C++14以降) 、メンバ関数テンプレート、またはクラステンプレートのメンバ関数もしくは静的データメンバが明示的インスタンス化定義によって明示的にインスタンス化される場合、そのテンプレート定義は同じ翻訳単位に存在しなければなりません。
クラステンプレートの特殊化を明示的なインスタンス化が指定する場合、それは翻訳単位内で以前に明示的に特殊化されていない非継承の非テンプレートメンバーそれぞれに対して、同じ種類(宣言または定義)の明示的なインスタンス化として機能します。この明示的なインスタンス化が定義である場合、この時点で定義されているメンバーに対してのみ、明示的なインスタンス化定義でもあります。
明示的なインスタンス化定義はメンバアクセス指定子を無視します:パラメータ型と戻り値の型はprivateであっても構いません。
暗黙のインスタンス化
コードが完全に定義された型を必要とする文脈でテンプレートを参照する場合、または型の完全性がコードに影響を与え、この特定の型が明示的にインスタンス化されていない場合、暗黙的インスタンス化が発生します。例えば、この型のオブジェクトが構築される場合ですが、この型へのポインタが構築される場合には発生しません。
これはクラステンプレートのメンバーに適用されます:メンバーがプログラム内で使用されない限り、インスタンス化されず、定義を必要としません。
template<class T> struct Z // テンプレート定義 { void f() {} void g(); // 定義されていない }; template struct Z<double>; // Z<double>の明示的インスタンス化 Z<int> a; // Z<int>の暗黙的インスタンス化 Z<char>* p; // ここでは何もインスタンス化されない p->f(); // ここでZ<char>とZ<char>::f()の暗黙的インスタンス化が発生 // Z<char>::g()は必要とされず、インスタンス化もされない: // 定義されている必要はない
クラステンプレートが宣言されているが、インスタンス化時点で定義されていない場合、インスタンス化は不完全なクラス型を生成します:
template<class T> class X; // 宣言、定義ではない X<char> ch; // エラー: 不完全型 X<char>
| ローカルクラス およびそのメンバーで使用されるテンプレートは、ローカルクラスまたは列挙型が宣言されているエンティティのインスタンス化の一部としてインスタンス化されます。 | (C++17以降) |
キーワード
export (C++11まで) extern (C++11以降)
関連項目
- テンプレートパラメータと引数 によりテンプレートをパラメータ化できます
- 関数テンプレート宣言 は関数テンプレートを宣言します
- テンプレート特殊化 は特定の型に対して既存のテンプレートを定義します
- パラメータパック によりテンプレート内での型リストの使用が可能になります (C++11以降)