在我正在研究的项目的一些序列化代码中,我有一个类型,其大小取决于编译器.为了解决这个问题,我决定使用模板专业化,这非常有效.一切都在编译时解决.代码看起来有点像这样(不是真正的代码,只是一个例子):
template <int size>
void
special_function()
{
std::cout << "Called without specialization: " << size << std::endl;
}
template <>
void
special_function<4>()
{
std::cout << "dword" << std::endl;
}
template <>
void
special_function<8>()
{
std::cout << "qword" << std::endl;
}
int
main()
{
special_function<sizeof(int)>();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在我的32位系统上dword,按预期执行上述程序输出.但这样做的全部意义并不仅仅是if (sizeof(int) == 4) { ... } else if ...我希望编译器只为适当的函数生成代码.由于special_function<4>是这个程序中唯一调用的,我希望它是编译器生成的唯一一个(在本例中为gcc 4.1.2,在x86 Linux上).
但这不是观察到的行为.
虽然它确实有效,但每个模板专业化的代码都会生成,尽管从未使用过.但是,不生成通用定义.
我应该提一下,这是一步编译,而不是编译到中间对象文件后跟一个链接.在这种情况下,将死代码删除推迟到链接阶段似乎很自然,我知道链接器并不总是非常擅长这一点.
有谁知道发生了什么?我在这里缺少模板专业化的微妙之处吗?上帝知道魔鬼在C++的细节中.
编辑:因为它已被提及,这种行为发生在-O3和-Os.
EDIT2:Rob建议将函数放在匿名命名空间中.这样做并使用任何级别的优化进行编译确实会删除死代码,这很好.但我很好奇,所以我尝试用以下程序做同样的事情:
namespace {
void foo() { std::cout << "Foo!" << …Run Code Online (Sandbox Code Playgroud)