编写模板函数(或成员)时,必须在头文件中编写正文。这非常有意义,因为模板本质上是指示编译器如何在初始化之前基于未知类型动态创建函数。
我的问题与一个定义规则有关,如果我在两个不同的文件中初始化具有相同类型的模板(例如 typename T 变为 int )将它们链接在一起我没有多重定义错误。
是什么原因?模板函数是否隐式静态,因此在编译单元外部不可见?
还是有另一个原因?
答案: 不,他们不是。它们是一个定义规则的例外。
答案 0 :(得分:3)
标准在模板的一个定义规则中包含一个特殊例外。
N4140,强调我的:
3.2一个定义规则[basic.def.odr]
6类类型(第9条),枚举类型(7.2),带内部链接的内联函数(7.1.2),类模板(第14条),非静态的定义可以有多个函数模板(14.5.6),类模板的静态数据成员(14.5.1.3),类模板的成员函数(14.5.1.1),或未指定某些模板参数的模板特化(14.7) ,14.5.5)在一个程序中提供了每个定义 出现在不同的翻译单元中,并且定义满足以下要求。 [...]
以下要求有效地说明所有定义必须相同,但我假设它们在您的代码中。
您可以通过此程序的工作原理判断模板函数既不隐式inline
也不隐式static
:
a.cc:
template <typename T> T f();
int main() { return f<int>(); }
b.cc:
template <typename T> T f() { return T(); }
template int f();
如果模板是隐式inline
,则此程序将无效,因为必须在使用它的每个翻译单元中定义inline
函数。
如果模板是隐式static
,则此程序将无效,因为b.cc
中的定义与a.cc
中的声明不匹配。