クラステンプレート
クラステンプレートは、クラスのファミリーを定義します。
目次 |
[編集] 構文
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については、プログラム全体で1回のみ記述が許可され、診断は不要です。
|
明示的インスタンス化宣言(externテンプレート)は、暗黙的インスタンス化ステップをスキップします。暗黙的インスタンス化を引き起こすコードは、代わりに他の場所で提供された明示的インスタンス化定義を使用します(そのようなインスタンス化が存在しない場合はリンクエラーが発生します)。これは、テンプレートのインスタンス化を使用するソースファイルのうち1つを除くすべてのファイルで明示的に宣言し、残りのファイルで明示的に定義することで、コンパイル時間を短縮するために使用できます。 |
(C++11以降) |
クラス、関数、変数(C++14以降)、およびメンバテンプレートの特殊化は、テンプレートから明示的にインスタンス化できます。クラステンプレートのメンバ関数、メンバクラス、および静的データメンバは、メンバ定義から明示的にインスタンス化できます。
修飾IDを使用しない限り、明示的インスタンス化はテンプレートを囲む名前空間にのみ現れます。
namespace N { template<class T> class Y // template definition { void mf() {} }; } // template class Y<int>; // error: class template Y not visible in the global namespace using N::Y; // template class Y<int>; // error: explicit instantiation outside // of the namespace of the template template class N::Y<char*>; // OK: explicit instantiation template void N::Y<double>::mf(); // OK: explicit instantiation
同じテンプレート引数のセットに対して明示的特殊化が以前に現れた場合、明示的インスタンス化は効果がありません。
関数テンプレート、変数テンプレート(C++14以降)、クラステンプレートのメンバ関数または静的データメンバ、またはメンバ関数テンプレートを明示的にインスタンス化する場合、宣言のみが表示される必要があります。同じテンプレート引数を持つ明示的特殊化が以前に現れた場合を除き、クラステンプレート、クラステンプレートのメンバクラス、またはメンバクラステンプレートの明示的インスタンス化の前に完全な定義が表示される必要があります。
関数テンプレート、変数テンプレート(C++14以降)、メンバ関数テンプレート、またはクラステンプレートのメンバ関数または静的データメンバが明示的インスタンス化定義で明示的にインスタンス化される場合、テンプレート定義は同じ翻訳単位に存在する必要があります。
明示的インスタンス化がクラステンプレート特殊化を指す場合、それは、翻訳単位で以前に明示的に特殊化されていなかったその非継承非テンプレートメンバのそれぞれに対して、同じ種類の明示的インスタンス化(宣言または定義)として機能します。この明示的インスタンス化が定義である場合、それはこの時点で定義されているメンバに対してのみ明示的インスタンス化定義でもあります。
明示的インスタンス化定義はメンバアクセス指定子を無視します。パラメータ型と戻り値の型はprivateでも構いません。
[編集] 暗黙的インスタンス化
完全に定義された型を必要とするコンテキストでテンプレートが参照される場合、または型の完全性がコードに影響する場合、およびこの特定の型が明示的にインスタンス化されていない場合、暗黙的インスタンス化が発生します。例えば、この型のオブジェクトが構築される場合ですが、この型へのポインタが構築される場合はそうではありません。
これはクラステンプレートのメンバに適用されます。メンバがプログラムで使用されない限り、インスタンス化されず、定義を必要としません。
template<class T> struct Z // template definition { void f() {} void g(); // never defined }; template struct Z<double>; // explicit instantiation of Z<double> Z<int> a; // implicit instantiation of Z<int> Z<char>* p; // nothing is instantiated here p->f(); // implicit instantiation of Z<char> and Z<char>::f() occurs here. // Z<char>::g() is never needed and never instantiated: // it does not have to be defined
インスタンス化の時点でクラステンプレートが宣言されているが定義されていない場合、インスタンス化は不完全なクラス型になります。
template<class T> class X; // declaration, not definition X<char> ch; // error: incomplete type X<char>
| ローカルクラスおよびそのメンバで使用されるテンプレートは、ローカルクラスまたは列挙型が宣言されているエンティティのインスタンス化の一部としてインスタンス化されます。 | (C++17以降) |
[編集] キーワード
export(C++11まで)extern(C++11以降)
[編集] 関連項目
- テンプレートパラメータと引数によりテンプレートをパラメータ化できます
- 関数テンプレート宣言は関数テンプレートを宣言します
- テンプレートの特殊化は、特定の型について既存のテンプレートを定義します
- パラメータパックは、テンプレートでの型のリストの使用を許可します(C++11以降)