我的模板专业化与调试版本和发布版本不同,这是gcc的错误吗?

时间:2016-10-11 11:32:18

标签: c++ templates symbols specialization weak

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

$ cat foo.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 foo\n");
}

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

最后我得到了一个主文件

$ cat main.cpp
#include "foo.h"

int main(){
  foo<int>::init();
  foo<float>::init();
}

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

  

g ++ foo_int.cpp foo_float.cpp main.cpp&amp;&amp; a.out的
  init int foo
  init float foo

如果我添加优化,那么结果就不同了:

  

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

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

  
      
  1. 是&#34;弱符号&#34; /&#34;强符号&#34; gcc / g ++的概念,或者它是c / c ++语言规范的一部分。

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

  4.   

我试过铿锵,不幸的是同样的错误。这是一个&#34;可接受的&#34;调试/发布的C / C ++案例&#34;应该&#34;表现得如此不同?

2 个答案:

答案 0 :(得分:3)

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

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

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

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

答案 1 :(得分:3)

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

  

如果是模板,成员模板或类模板的成员   明确专业化然后宣布专业化   在第一次使用该特化之前会导致一个   隐式实例化发生在每个翻译单元中   发生了这种用途;无需诊断。 [temp.expl.spec] / 6。

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