显式实例化

显式实例化定义从模板创建并声明具体的类,函数或变量,而不使用它。可以从其他翻译单元引用显式实例化。这可用于避免在头文件中定义模板,如果它仅使用有限的参数集进行实例化。例如:

// print_string.h
template <class T>
void print_string(const T* str);

// print_string.cpp
#include "print_string.h"
template void print_string(const char*);
template void print_string(const wchar_t*);

因为 print_string<char>print_string<wchar_t> 是在 print_string.cpp 中显式实例化的,所以即使未在头文件中定义 print_string 模板,链接器也能够找到它们。如果不存在这些显式实例化声明,则可能会发生链接器错误。请参阅为什么模板只能在头文件中实现?

Version >= C++ 11

如果显式实例化定义前面是 extern 关键字 ,则它将成为显式实例化声明。给定特化的显式实例化声明的存在阻止了当前转换单元内给定特化的隐式实例化。相反,对该特化的引用否则将导致隐式实例化可以引用相同或另一个 TU 中的显式实例化定义。

foo.h

#ifndef FOO_H
#define FOO_H
template <class T> void foo(T x) {
    // complicated implementation
}
#endif

foo.cpp

#include "foo.h"
// explicit instantiation definitions for common cases
template void foo(int);
template void foo(double);

main.cpp

#include "foo.h"
// we already know foo.cpp has explicit instantiation definitions for these
extern template void foo(double);
int main() {
    foo(42);   // instantiates foo<int> here;
               // wasteful since foo.cpp provides an explicit instantiation already!
    foo(3.14); // does not instantiate foo<double> here;
               // uses instantiation of foo<double> in foo.cpp instead
}