命名空间
变体
操作

类模板

来自 cppreference.cn
< cpp‎ | 语言
 
 
C++ 语言
 
 
 
 

类模板定义了一系列类。

目录

[编辑] 语法

template < 参数列表 > 类声明 (1)
template < 参数列表 > requires 约束 类声明 (2) (C++20 起)
export template < 参数列表 > 类声明 (3) (在 C++11 中已移除)

[编辑] 解释

类声明 - 一个类声明。声明的类名成为模板名。
参数列表 - 一个非空的逗号分隔的模板参数列表,每个参数都是非类型参数类型参数模板参数或这些参数的参数包
约束 - 一个约束表达式,它限制此类模板接受的模板参数。
export 是一个可选修饰符,用于将模板声明为已导出(与类模板一起使用时,它也将其所有成员声明为已导出)。实例化导出模板的文件不需要包含其定义:声明就足够了。export 的实现很少见,并且在细节上彼此不一致。 (C++11 前)

[编辑] 类模板实例化

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

[编辑] 显式实例化

template 类键 模板名 < 参数列表 > ; (1)
extern template 类键 模板名 < 参数列表 > ; (2) (C++11 起)
类键 - class, structunion
1) 显式实例化定义
2) 显式实例化声明

显式实例化定义强制实例化它们所引用的类、结构体或联合体。它可以在模板定义之后的程序中的任何位置出现,对于给定的参数列表,在整个程序中只允许出现一次,不需要诊断。

显式实例化声明 (extern template) 跳过隐式实例化步骤:否则会导致隐式实例化的代码会使用其他地方提供的显式实例化定义(如果不存在此类实例化,则会导致链接错误)。这可以用于通过在所有使用它的源文件(除一个文件外)中显式声明模板实例化,并在剩余文件中显式定义它来减少编译时间。

(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 起)、成员函数模板或类模板的成员函数或静态数据成员通过显式实例化定义进行显式实例化,则模板定义必须存在于同一翻译单元中。

当显式实例化命名类模板特化时,它作为其每个尚未在翻译单元中显式特化的非继承非模板成员的相同种类(声明或定义)的显式实例化。如果此显式实例化是一个定义,它也仅是此时已定义的成员的显式实例化定义。

显式实例化定义忽略成员访问说明符:参数类型和返回类型可以是私有的。

[编辑] 隐式实例化

当代码在需要完全定义类型的上下文中引用模板,或者当类型的完整性影响代码时,并且此特定类型尚未显式实例化时,会发生隐式实例化。例如,当此类型的对象被构造时,但当此类型的指针被构造时则不会。

这适用于类模板的成员:除非在程序中使用该成员,否则它不会被实例化,也不需要定义。

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 起)

[编辑] 另见