模板

template 这个词是一个关键词 ,在 C++语言中有五种不同的含义,具体取决于上下文。

  1. 当后面跟着 <> 中包含的模板参数列表时,它会声明一个模板,例如类模板函数模板或现有模板的部分特化。

    template <class T>
    void increment(T& x) { ++x; }
    
  2. 当后面跟着一个空的 <> 时,它会声明一个显式(完整)特化

    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);
    }
    
  3. 当后面跟不带 <> 的声明时,它形成一个显式的实例化声明或定义。

    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
    
  4. 在模板参数列表中,它引入了模板模板参数

    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));
        }
        // ...
    };
    
  5. 在范围解析运算符::和类成员访问运算符 .-> 之后,它指定以下名称是模板。

    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 关键字是违法的。相反,通常需要在头文件中定义模板(与非模板函数相反,非模板函数通常不在头文件中定义)。请参阅为什么模板只能在头文件中实现?