14. 模板
1. 模板定义了一族函数或类。
模板声明 :
export opt template < 模板参数列表 > 声明
模板参数列表 :
模板参数
模板参数列表 , 模板参数
模板声明 中的声明 部分应该:
1) 声明或定义一个函数或类,或者
2) 定义一个类模板或类模板的嵌套类的成员函数、成员类或静态数据成员,或者
3) 定义一个类的成员模板或类模板。
模板声明 是个声明。如果其声明 部分定义了一个函数、类或静态数据成员的话,模板声明 就是个定义。
2. 模板声明 只能作为名字空间域或类域的声明出现。在函数模板声明中, declarator-id 必须是模板名字(就是说,不能是模板 id )。【注:在类模板声明中,如果类名是模板 id ,那么该声明就是一个类模板的偏特化。】
3. 在模板声明 、显式特化、显式实例化中,声明中的初始声明符列表最多只能出现一个声明符。当这样的声明用来声明类模板的时候是不允许出现声明符的。
4. 模板名有链接性。非成员的函数模板可以有内部链接;其他任何模板名都必须是外部链接。具有内部链接性的模板生成的实体与在其他翻译单元中生成的所有实体都不等同。模板、模板显式实例化或类模板偏特化不能有 C 链接性;如果上述这些东西的链接既不是 C 也不是 C++ 的,那它的行为就是随具体编译器实现而定的。模板定义必须遵守一定义原则。【注:函数模板和类模板成员函数的默认参数被认为是定义(由于模板会被实例化),也必须遵守一定义原则。】
5. 除了 14.5.4 中说明的情况,类模板的名字不能与任何其他同作用域的模板、类、函数、对象、枚举、枚举器、名字空间、数据类型的名字相同。除了函数模板可以被同名的(非模板)函数或其他同名的函数模板重载外,名字空间域或类域中的模板名必须唯一。
6. 对于名字空间域中的非内联函数模板、非内联成员函数模板、类模板的非内联成员函数、类模板的静态数据成员,这些东西的声明或定义之前可以加个关键字: export 。假如这种模板(带 export 关键字)的声明与定义在同一个翻译单元中,那么其定义就被认为是输出型的。模板的第一个包含 export 关键字的声明之后不必非得跟着其定义。
7. 声明一个输出型的类模板等价于将定义在本翻译单元中的其所有非内联成员函数、静态成员、成员类、成员类模板、非内联成员函数模板都声明为输出型的。
8. 定义在匿名名字空间中的模板不能是输出型的。一个程序中,模板只能被输出一次;如果程序代码与该规则冲突,不需要编译器给出诊断信息。非输出型的模板必须在其每个隐式实例化的翻译单元中定义,除非相应的特化在某个翻译单元中被显式实例化了;不需要编译器给出诊断信息。【注:参见 14.7.2 】输出型的模板在其实例化的翻译单元中,只需要有个声明就行了,不必定义。声明为输出类型的内联函数模板仅仅是内联的,不是输出型的。
【按:模板级的export 相当于函数级的extern ;内联的作用力比export 更强。】
9. 【注:编译器的具体实现可能会要求:一个包含输出型模板的翻译单元必须先编译,然后其他翻译单元才能将该模板实例化。】