【问题标题】:My template specialization differs debug version from release version, is this gcc bug?我的模板专业化调试版本与发布版本不同,这是 gcc 错误吗?
【发布时间】:2016-10-11 11:32:18
【问题描述】:

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

$ 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 && a.out
初始化 int foo
初始化浮动 foo

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

$ g++ foo_int.cpp foo_float.cpp main.cpp -O2 && a.out
初始化 int foo

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

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

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

我试过clang,不幸的是同样的错误。对于调试/发布“应该”表现如此不同的 C/C++,这是一个“可接受的”案例吗?

【问题讨论】:

  • void foo&lt;float&gt;::init() 的专业化声明在 main 中不可见...您的程序格式不正确。
  • 格式化文本时要小心。只有代码块保留空格和换行符。当您将g++ 控制台输出粘贴到&gt; 标记下时,它忽略了换行符,所有换行符都被压缩成一行文本。要保留换行符,请在每行的末尾放置一个双空格。或者只是粘贴作为代码块。读者通常可以毫无问题地注意到哪一个包含代码,哪一个包含控制台转储:)
  • “我有一个类的头文件”——不,你有一个模板的头文件。
  • 在头文件中声明显式实例化的头或者使用extern template

标签: c++ templates symbols specialization weak


【解决方案1】:

语言定义要求您在使用之前声明一个明确的特化:

如果模板、成员模板或类模板的成员是 显式特化,则应声明特化 在第一次使用会导致 隐式实例化发生在每个翻译单元中 发生这种使用;不需要诊断。 [temp.expl.spec]/6.

foo&lt;float&gt;::init() 在从main 调用时没有显式特化的声明,但在foo_float.cpp 中有显式特化,因此程序的行为是未定义的。

【讨论】:

    【解决方案2】:

    你违反了一个定义规则——你的程序包含两个foo&lt;float&gt;::init的定义。

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

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

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

    【讨论】:

    • main.cpp 中:因为没有foo&lt;float&gt;::init 特化声明,那么一般认为foo&lt;float&gt;::init 的定义?是这个原因吗?
    猜你喜欢
    • 2018-09-08
    • 1970-01-01
    • 2010-10-27
    • 2020-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多