首页 > 解决方案 > C++:对模板使用“extern”关键字有什么意义吗?

问题描述

考虑以下示例:

fnc.h:

#include <iostream>

template <class T> //common template definition
void fnc()
{
    std::cout << "common";
}

fnc.cpp:

#include "fnc.h"

template<> //specialization for "int"
void fnc<int>()
{
    std::cout << "int";
}

主文件

#include "fnc.h"

extern template void fnc<int>(); // compiler will not generate fnc<int> and linker will be used to find "fnc<int>" in other object files

int main()
{
    fnc<double>(); //using instantiation from common template
    fnc<int>(); using specialization from "fnc.cpp"
}

然后我替换extern template void fnc<int>();template<> void fnc<int>();并假设行为将相同。extern将关键字与模板一起使用是否有任何实际意义,还是仅出于可读性而引入?

标签: c++templateslinkerinstantiationextern

解决方案


不是针对专业的。从技术上讲,您所做的事情是不正确的,不需要诊断。您有一个明确的实例化声明,但没有匹配的定义。显式特化不计入与您提供的声明的匹配(即使某些编译器以隐藏事实的方式实现它)。

此构造用于延迟实例化,以使编译器不会尝试在当前翻译单元中实例化模板。因此,您可以使用它来完全隐藏模板并仅针对有限的一组类型公开:

标题:

template <class T>
void fnc();

extern template void fnc<int>(); // The instantiation is elsewhere.

资源:

template <class T> //common template definition
void fnc()
{
    std::cout << "common";
}

template void fnc<int>(); // explicit instantiation

或者为了防止在每个 TU 中实例化常用的特化:

通用标题:

#include <vector>
extern template std::vector<unsigned char>; // look for member definitions elsewhere.

一个源文件:

template std::vector<unsigned char>; // The member functions are defined in this TU

后面的用例可能会节省编译时间。


推荐阅读