模板
template
这个词是一个关键词 ,在 C++语言中有五种不同的含义,具体取决于上下文。
-
当后面跟着
<>
中包含的模板参数列表时,它会声明一个模板,例如类模板 ,函数模板或现有模板的部分特化。template <class T> void increment(T& x) { ++x; }
-
当后面跟着一个空的
<>
时,它会声明一个显式(完整)特化 。template <class T> void print(T x); template <> // <-- keyword used in this sense here void print(const char* s) { // output the content of the string printf("%s\n", s); }
-
当后面跟不带
<>
的声明时,它形成一个显式的实例化声明或定义。template <class T> std::set<T> make_singleton(T x) { return std::set<T>(x); } template std::set<int> make_singleton(int x); // <-- keyword used in this sense here
-
在模板参数列表中,它引入了模板模板参数 。
template <class T, template <class U> class Alloc> // ^^^^^^^^ keyword used in this sense here class List { struct Node { T value; Node* next; }; Alloc<Node> allocator; Node* allocate_node() { return allocator.allocate(sizeof(T)); } // ... };
-
在范围解析运算符
::
和类成员访问运算符.
和->
之后,它指定以下名称是模板。struct Allocator { template <class T> T* allocate(); }; template <class T, class Alloc> class List { struct Node { T value; Node* next; } Alloc allocator; Node* allocate_node() { // return allocator.allocate<Node>(); // error: < and > are interpreted as // comparison operators return allocator.template allocate<Node>(); // ok; allocate is a template // ^^^^^^^^ keyword used in this sense here } };
在 C++ 11 之前,可以使用 export
关键字声明模板,使其成为导出的模板。导出模板的定义不需要出现在实例化模板的每个转换单元中。例如,以下应该起作用:
foo.h
:
#ifndef FOO_H
#define FOO_H
export template <class T> T identity(T x);
#endif
foo.cpp
:
#include "foo.h"
template <class T> T identity(T x) { return x; }
main.cpp
:
#include "foo.h"
int main() {
const int x = identity(42); // x is 42
}
由于实施困难,大多数主要编译器都不支持 export
关键字。它在 C++ 11 中删除了; 现在,完全使用 export
关键字是违法的。相反,通常需要在头文件中定义模板(与非模板函数相反,非模板函数通常不在头文件中定义)。请参阅为什么模板只能在头文件中实现?