我怀疑gcc 4.8.3是否内联不正确的模板函数......在调试模式下不会出现此问题,但仅在优化模式下。然而,这发生在复杂的代码库中,我无法在简单的测试用例中重现该问题。
我的代码如下
#include "stdio.h"
class A {
public:
template<typename T> int WriteNative(const T) {
printf("here?\n")
return 0;
}
template<typename D>
void doit() {
if (WriteNative<double>(1)) {
printf("A\n");
} else {
printf("B\n");
}
}
};
// in my real code, this definition is in a different cpp file
template<> int A::WriteNative<double>(const double) {
return 1;
}
int main() {
A a;
a.doit<float>();
}
在调试版本中,它打印出A,而在优化版本中,它会打印出来吗?\ nB
我猜任何内联都使用通用模板函数定义,但不使用专用函数定义。但属性((noinline))无济于事。
如果我的代码具有C ++的已定义行为,是否有人?以及如何解决这个问题?
答案 0 :(得分:2)
您没有明确说明这一点,但我在您的实际代码中猜测您未能在A
的.h文件中声明专业化。因此,当A.h
包含在单独的编译单元中时,编译器不知道WriteNative()
的特殊值。添加专业化声明应该解决问题,而不必将定义包含在同一个文件中(即,不必内联它):
class A {
public:
template<typename T> int WriteNative(const T) {
printf("here?\n")
return 0;
}
template<typename D>
void doit() {
if (WriteNative<double>(1)) {
printf("A\n");
} else {
printf("B\n");
}
}
};
template<> int A::WriteNative(const double);
您可以使用三个文件A.h
,A.cpp
和main.cpp
来重现您的问题,其中A.cpp
包含专精的定义,以便在{{1包含main.cpp
,在优化期间发生内联时不知道特化,当使用A.h
进行编译时,不会发生内联,因此-O0
与{{1}中的定义相关联}}
编辑: 请参阅此answer,其中引用了规范来解释为什么这是正确的行为。
14.7.3 [temp.expl.spec]:
6 /如果是模板,成员模板或类模板的成员 明确专业化然后宣布专业化 在第一次使用该特化之前会导致一个 隐式实例化发生在每个翻译单元中 发生了这种用途;无需诊断。如果是程序 没有为显式专业化提供定义 专业化的使用方式会导致 隐式实例化发生或成员是虚拟成员 功能,程序格式错误,无需诊断。一个 永远不会为显式生成隐式实例化 声明但未定义的特化。