c – G为未使用的模板特化生成代码?

c – G为未使用的模板特化生成代码?,第1张

概述在我正在研究的项目的一些序列化代码中,我有一个类型,其大小取决于编译器.为了解决这个问题,我决定使用模板专业化,这非常有效.一切都在编译时解决.代码看起来有点像这样(不是真正的代码,只是一个例子): template <int size>voidspecial_function(){ std::cout << "Called without specialization: " << 在我正在研究的项目的一些序列化代码中,我有一个类型,其大小取决于编译器.为了解决这个问题,我决定使用模板专业化,这非常有效.一切都在编译时解决.代码看起来有点像这样(不是真正的代码,只是一个例子):
template <int size>voIDspecial_function(){     std::cout << "Called without specialization: " << size << std::endl;}template <>voIDspecial_function<4>(){     std::cout << "DWord" << std::endl;}template <>voIDspecial_function<8>(){     std::cout << "qword" << std::endl;}intmain(){     special_function<sizeof(int)>();     return 0;}

在我的32位系统上,按预期执行上述程序输出DWord.但这样做的全部意义并不是只做if(sizeof(int)== 4){…}如果……是我希望编译器只为适当的函数生成代码.由于special_function< 4>是这个程序中唯一调用的,我希望它是编译器生成的唯一一个(在本例中是gcc 4.1.2,在x86 linux上).

但这不是观察到的行为.

虽然它确实有效,但每个模板专业化的代码都会生成,尽管从未使用过.但是,不生成通用定义.

我应该提一下,这是一步编译,而不是编译到中间对象文件后跟一个链接.在这种情况下,将死代码删除推迟到链接阶段似乎很自然,我知道链接器并不总是非常擅长这一点.

有谁知道发生了什么?我在这里缺少模板专业化的微妙之处吗?上帝知道魔鬼与C有关.

编辑:因为它已被提及,这种行为发生在-O3和-Os.

EDIT2:Rob建议将函数放在匿名命名空间中.这样做并使用任何级别的优化进行编译确实会删除死代码,这很好.但我很好奇,所以我尝试用以下程序做同样的事情:

namespace {voID foo() { std::cout << "Foo!" << std::endl; }voID bar() { std::cout << "bar!" << std::endl; }}intmain(){       foo();       return 0;}

这里的想法是看看Rob的解决方案是否实际上与模板特化相关.事实证明,上面编译时启用了优化的代码省略了可执行文件中未使用的bar()定义.所以看来,虽然他的答案解决了我的直接问题,但它并没有解释为什么根本没有编译未使用的模板特化.

有没有人知道标准中的相关片段可以解释这一点?我一直认为模板只是在使用时生成的,但对于完全专业化可能并非如此……

解决方法 示例中的模板特化是具有外部链接的函数.编译器无法知道不会从另一个翻译单元调用它们.

在我的g 4.7.2 Ubuntu系统上,将模板放入匿名命名空间并使用-O3或-O4进行编译可防止生成未使用的函数.

同样,声明函数模板static会产生预期的效果.

总结

以上是内存溢出为你收集整理的c – G为未使用的模板特化生成代码?全部内容,希望文章能够帮你解决c – G为未使用的模板特化生成代码?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1255460.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存