我怀疑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++行为,还有人吗?以及如何解决这个问题?
发布于 2017-05-03 04:13:56
您没有显式地声明这一点,但在实际代码中,我猜您没有在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包含专门化的定义,因此当main.cpp包含A.h时,它不知道在优化期间发生内联时的专门化,而使用-O0编译时不会出现内联,因此WriteNative()将根据A.cpp中的定义进行链接。
编辑:看这个answer,它引用了规范来解释为什么这是正确的行为。
14.7.3 temp.expl.spec
6如果模板、成员模板或类模板的成员明确地专门化,则应在首次使用该专门化之前声明该专门化,这将导致在发生这种使用的每个翻译单元中进行隐式实例化;不需要进行诊断。如果程序没有为显式专门化提供定义,并且使用专门化的方式会导致隐式实例化发生,或者成员是虚拟成员函数,则程序是格式错误的,不需要诊断。不为声明但未定义的显式专门化生成隐式实例化。
https://stackoverflow.com/questions/43750053
复制相似问题