C++:模板特化导致调试/发布中的不同结果

标签 c++ templates

在下面的代码中,我创建了一个 Builder 模板,并提供了一个默认实现以不返回任何内容。然后我使用 int 专门化模板,以返回值 37。

当我使用-O0编译时,代码打印37,这是预期的结果。但是当我使用 -O3 编译时,代码打印 0。

平台是Ubuntu 20.04,GCC 9.3.0

任何人都可以帮助我理解这种行为吗?

builder.h

class Builder {
        public:
                template<typename C>
                static C build() {
                        return 0;
                }
};

builder.cc

#include "builder.h"

template<>
int Builder::build<int>() {
        return 37;
}

main.cc

#include "builder.h"
#include <iostream>

int main() {
        std::cout << Builder::build<int>() << '\n';
}

生成文件

CXX_FLAG = -O0 -g
all:
        g++ $(CXX_FLAG) builder.cc -c -o builder.o
        g++ $(CXX_FLAG) main.cc builder.o -o main
clean:
        rm *.o
        rm main

最佳答案

您应该为 build<int>() 添加前向声明至builder.h ,像这样:

template<>
int Builder::build<int>();

否则,编译时main.cc ,编译器只能看到通用模板,并且允许内联通用 build() 的实例。功能。如果您添加前向声明,编译器就会知道您在其他地方提供了专门化,并且不会内联它。

-O3 ,编译器尝试内联,使用 -O0它不会内联任何内容,因此存在差异。

您的代码实际上违反了 "One Definition Rule" :它将为 Builder::build<int>() 创建两个定义,但它们并不相同。标准称结果未定义,但不需要诊断。在这种情况下有点不幸,因为如果生成警告或错误消息会很有帮助。

关于C++:模板特化导致调试/发布中的不同结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65876360/

相关文章:

C++03 链接器 "already defined symbol"没有出现在中间文件中

c++ - 启用非模板成员函数,前提是它会进行类型检查

c++ - 为什么挂钟比 cpu 用户/内核时间高很多

Outlook 表格宽度问题中的 HTML 电子邮件 - 内容比指定的表格宽度宽

c++ - PrintTo 用于 Google Test 中的指针

c++ - Qt 中的 os.path.join()?

C++ 模板构造函数

templates - Meteor:在用数据渲染模板后调用函数

c++ - zGuide for zeroMQ 编译失败

c++ - 为 Structs C++ 的 vector 创建大小时出错