我的模板专用化与发布版本不同调试版本,是这个 gcc 错误



首先,我有一个类的头文件,一个没有定义的专用声明(来自互联网的代码示例(

$ 猫福.h

template<typename T>
class foo{
public:
  static void init(){
      return;
  }
};
template<>  void foo<int>::init();

然后有 2 个用于模板专用化的实现文件

$ cat foo_int.cpp 
#include "foo.h"
#include<stdio.h>
template<>
void foo<int>::init(){
    printf("init int foon");
}
$ cat foo_float.cpp 
#include "foo.h"
#include<stdio.h>
template<>
void foo<float>::init(){
    printf("init float foon");
}

终于我得到了一个主文件

$ cat main.cpp
#include "foo.h"
int main(){
  foo<int>::init();
  foo<float>::init();
}

如果我在没有优化的情况下编译它并运行它,它会给出:

g++ foo_int.cpp foo_float.cpp main.cpp && a.out
init int foo
初始化浮动 foo

如果我添加优化,那么结果会有所不同:

$ g++ foo_int.cpp foo_float.cpp main.cpp -O2 && a.out
init int foo

结果是不同的。来自互联网的一些解释说这是由于 gcc 实现中的一些"弱符号"的内部机制,但我的问题:

    "弱符号"/
  1. "强符号"是 gcc/g++ 的概念,还是 c/c++ 语言规范的一部分。

  2. 如果调试和发布结果不同,我应该说这是 gcc/g++ 的一个错误/问题,关于"弱符号"机制?作为开发人员,我不希望我的调试版本与发布版本的行为不同。

我尝试了叮当声,不幸的是同样的错误。对于 C/C++来说,调试/发布"应该"的行为如此不同,这是否是一个"可接受的"情况?

语言定义要求您在使用之前声明显式专用化:

如果模板、成员模板或类模板的成员是 明确专业化,然后应声明专业化 在首次使用该专业化之前,会导致 隐式实例化发生在 发生此类用途;无需诊断。[温度规范]/6.

在从

main调用foo<float>::init()时没有声明显式的特化,但是在foo_float.cpp中有一个显式的特化,所以程序的行为是未定义的。

你违反了一个定义规则——你的程序包含两个foo<float>::init定义。

一个定义出现在编译单元foo_float.cpp,另一个定义出现在编译单元main.cpp中。

违反一个定义规则意味着未定义的行为 — 在这种情况下,可能发生的情况是:

  • 关闭优化后,程序生成一个实际的函数调用,链接器碰巧将foo_float.cpp函数的版本放在可执行文件中。
  • 优化后,当编译main.cpp时,编译器会内联函数 — 自然地,它会内联main.cpp函数的版本。

最新更新