为什么模板专业化需要内联?
Why do templates specialisations need to be inlined?
我指的是这个答案:
https://stackoverflow.com/a/4447057/930315
我遇到了与所引用问题的OP类似的问题, 具有函数
template<typename T>
void func(T& val);
及其专业化
template<>
void func<mytype>(mytype& val);
导致重复符号链接器错误(这些方法在我的标头末尾包含的".tpp"文件中实现)。 向专用功能添加inline
解决了该问题。为什么?
好吧,如果你想要这方面的标准报价,那就在 [temp.expl.spec]/12 结束
了函数或变量模板的显式专用化是 仅当使用内联说明符声明或定义为内联时,才内联 已删除,并且与其函数或变量无关 模板是内联的。[ 示例:
template<class T> void f(T) { /* ... */ } template<class T> inline T g(T) { /* ... */ } template<> inline void f<>(int) { /* ... */ } // OK: inline template<> int g<>(int) { /* ... */ } // OK: not inline
— 结束示例 ]
这就是为什么你必须这样做。它是独立的,因为我相信否则会受到不必要的限制,正如 Yola 所证明的那样。
这将在没有内联的情况下工作:
文件1.h
template<typename T> void func(T& val);
template<> void func<mytype>(mytype& val);
文件1.cpp
template<> void func<int>(int& ) {}
但是,如果您在头文件中定义模板专用化,则可能会违反ODR
根据 c++ 标准中的条款 3.2:4
每个程序应只包含每个非内联的一个定义 该程序中使用的 ODR 函数或变量;无诊断 必填。定义可以显式出现在程序中,它可以 在标准或用户定义的库中找到,或者(当 适当)它是隐式定义的(见 12.1、12.4 和 12.8). 内联函数应在使用它的每个翻译单元中定义。
这就解释了为什么当专用函数未内联声明时会出现链接时错误。该程序将包含专用函数的多个定义,每个模块(包括.tpp文件)一个定义,这打破了标准中的条件。当声明专用函数inline
时,它将使函数满足同一子句的第二部分,即必须在使用该函数在每个模块中定义一个内联函数。
当参数化函数不是专用的时,它包含在条款 3.2:6 中:
类类型可以有多个定义(第 9 条), 枚举类型 (7.2)、带外部链接的内联函数 (7.1.2), 类模板(条款 14)、非静态函数模板 (14.5.6)、 类模板的静态数据成员 (14.5.1.3),成员函数 类模板 (14.5.1.1),或模板专用化,其中一些 程序中未指定模板参数(14.7、14.5.5) 前提是每个定义出现在不同的翻译单元中
此子句指出,只要代码中未指定至少一个模板参数,就可以对同一模板函数进行多个定义。这是为了允许仅根据本地信息决定是否应在模块中实例化参数化函数。
- 为什么在班级专业化上会出现错误?
- 为什么这个模板代码不选择部分专业化
- 为什么没有选择模板专业化?
- 为什么这不是函数模板的部分专业化
- 为什么VS2017拒绝我的功能模板专业化,而不是VS2015拒绝
- 为什么模板专业化需要内联?
- 为什么我们不能在模板专业化的开始/中间使用可变参数模板(以及如何模拟)?
- 为什么有这么多std::swap的专业化
- 为什么不允许对成员函数的模板专业化
- 为什么未经声明未从.cpp文件拾取模板函数的完整专业化
- 为什么这个不是完整的模板专业化
- 为什么这是部分专业化?(我能做什么?
- 为什么内联模板专业化有帮助?我应该这样做吗
- 为什么要使用模板专业化
- 为什么不能在完全专业化中引入新的模板参数?
- 为什么类中不允许函数模板专业化
- 为什么我的模板专业化不起作用
- 为什么显式专业化和部分专业化之间的语法差异
- 为什么未使用的部分专业化没有错误
- 为什么没有针对 std::shared_ptr<T[]> 的专业化?