类模板

来自cppreference.com
< cpp‎ | language

类模板定义一系列类。

目录

[编辑] 语法

template < parameter-list > class-declaration (1)
export template < parameter-list > class-declaration (2) (C++11 前)

[编辑] 解释

class-declaration - 一个类声明。声明的类名成为模板名。
parameter-list - 非空的模板形参逗号分隔列表,其中每项都是非类型模板形参类型模板形参模板模板形参参数包之一。
export 是一个可选的修饰符,声明模板为被导出(用于类模板时,它声明所有成员为导出)。带有实例化被导出模板的文件不需要包含其定义:有声明就足够了。 export 的实现稀少而且在细节上互不一致。 (C++11 前)

[编辑] 类模板实例化

类模板自身不是类型、对象或任何其他实体。从仅包含模板定义的源文件不生成任何代码。为了让任何代码出现,模板必须被实例化:必须提供模板实参,以令编译器能生成实际的类(或从函数模板生成函数)。

[编辑] 显式实例化

template class|struct template-name < argument-list > ; (1)
extern template class|struct template-name < argument-list > ; (2) (C++11 起)
1) 显式实例化定义
2) 显式实例化声明

显式实例化定义强制它们所指代的 class 、 struct 或 union 的实例化。它可以出现在模板定义后的任何位置,而对于给定的实参列表,只允许在整个程序中出现一次。

显式实例化声明( extern 模板)跳过隐式实例化的步骤:使用其他地方提供的显式实例化定义替代此外情况下产生的隐式实例化(若不存在这种实例化则产生链接错误)。这可用于减少编译时间,通过显式声明所有模板实例化于使用模板的源文件中,并在剩余文件中显式定义它。 (C++11 起)

类、函数、变量和成员模板特化可以从其模板显式实例化。类模板的成员函数、成员类、及静态数据成员可从其成员定义显式实例化。

显式实例化只能出现于模板所在的外围命名空间,除非它使用限定 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 :显式实例化

若对于同一组模板参数,显式特化提前出现,则显式实例化无效果。

在显式实例化函数模板、变量模板、类模板的成员函数或静态数据成员实例化时,只有声明要求可见。完整的定义必须先于类模板、类模板的成员类或成员类模板的显式实例化出现,除非拥有同一模板实参的显式特化提前出现。

若函数模板、变量模板、成员函数模板,或类模板的成员函数或静态成员数据被以显式实例化定义显式实例化,则模板定义必须存在于同一翻译单元中。

当显式实例化命名一个类模板特化时,它作为在翻译单元中未被显式特化的,其非继承非模板成员的同种(声明或定义)的显式实例化。若此显式实例化是定义,则它也是只对在此点已被定义的成员的显式实例化定义。

显式实例化定义忽略成员访问指定符:形参类型与返回类型可以为 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 起)

[编辑] 参阅