类模板
类模板定义了一族类。
内容 |
[编辑] 语法
template < 参数列表 > 类声明 |
(1) | ||||||||
template < 参数列表 > requires 约束 类声明 |
(2) | (自 C++20 起) | |||||||
export template < 参数列表 > 类声明 |
(3) | (在 C++11 中移除) | |||||||
[编辑] 解释
类声明 | - | 一个类声明。声明的类名成为模板名称。 |
参数列表 | - | 一个非空的逗号分隔的模板参数列表,每个参数都是一个非类型参数、一个类型参数、一个模板参数或一个参数包(可以是上述任何一种)。 |
约束 | - | 一个约束表达式,限制此类模板接受的模板参数 |
export 是一个可选的修饰符,它将模板声明为导出(当与类模板一起使用时,它将声明其所有成员也被导出)。实例化导出模板的文件不需要包含它们的定义:声明就足够了。export 的实现很少见,并且在细节上存在分歧。 |
(直到 C++11) |
[编辑] 类模板实例化
类模板本身不是类型,也不是对象,或任何其他实体。包含只有模板定义的源文件不会生成任何代码。为了让代码出现,模板必须被实例化:必须提供模板参数,以便编译器可以生成一个实际的类(或函数,从函数模板生成)。
[编辑] 显式实例化
template 类关键字 模板名称 < 参数列表 > ; |
(1) | ||||||||
extern template 类关键字 模板名称 < 参数列表 > ; |
(2) | (自 C++11 起) | |||||||
类关键字 | - | class , struct 或 union |
显式实例化定义强制实例化它们引用的类、结构或联合。它可以出现在程序中模板定义之后的任何位置,对于给定的参数列表,在整个程序中只允许出现一次,无需诊断。
显式实例化声明(extern 模板)跳过隐式实例化步骤:否则会导致隐式实例化的代码改为使用在其他地方提供的显式实例化定义(如果不存在此类实例化,则会导致链接错误)。这可以通过在所有使用它的源文件中显式声明模板实例化,并在剩余的一个文件中显式定义它来减少编译时间。 |
(自 C++11 起) |
类、函数, 变量(自 C++14 起)和成员模板特化可以从它们的模板中显式实例化。类模板的成员函数、成员类和静态数据成员可以从它们的成员定义中显式实例化。
显式实例化只能出现在模板的封闭命名空间中,除非它使用限定标识符
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 起)、成员函数模板、或类模板的成员函数或静态数据成员使用显式实例化定义进行显式实例化,则模板定义必须出现在同一个翻译单元中。
当显式实例化命名类模板特化时,它会作为相同种类(声明或定义)的每个未在翻译单元中显式特化的非继承非模板成员的显式实例化。如果此显式实例化是定义,它也只作为在此时已定义的成员的显式实例化定义。
显式实例化定义忽略成员访问说明符:参数类型和返回值类型可能是私有的。
[编辑] 隐式实例化
当代码在需要完全定义的类型的上下文中引用模板时,或者当类型的完整性影响代码时,并且此特定类型尚未显式实例化,就会发生隐式实例化。例如,当构造此类型的对象时,但当构造指向此类型的指针时不会发生。
这适用于类模板的成员:除非在程序中使用成员,否则不会实例化它,也不需要定义。
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 起)