在有些系列化代码的项目我的工作我有一个类型,其大小是依赖于编译器。 为了解决这个问题,我决定用一个模板专业化,伟大的工程。 一切都在编译时得到解决。 该代码看起来是这样一点点(不是真正的代码,只是一个例子):
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;
}
在我的32位系统中,执行上述程序输出dword
,如所预期。 但做这种方式,而不是只是在做整点if (sizeof(int) == 4) { ... } else if ...
是我所希望的,编译器将只生产代码,相应的功能。 由于special_function<4>
是在调用该程序唯一的一个,我希望它是唯一一个由编译器生成器(gcc 4.1.2在这种情况下,在x86的Linux)。
但是,这不是观察到的行为。
虽然它确实有效,则尽管没有被使用过生成每个模板专用的代码。 通用定义不产生,但是。
我应该指出,这是一个单步编译,而不是汇编成中介目标文件后面的链接。 在这种情况下,它似乎自然推迟删除死代码的链接阶段,我知道的接头是不是总是在这个非常好。
有谁知道这是怎么回事? 有我在这里失踪模板专业化的精妙之处? 上帝知道魔鬼与C ++的细节。
编辑:既然它已经提到的,既-O3和-Os出现这种情况。
EDIT2:下面罗布建议对功能在一个匿名的命名空间。 这样做,并与优化的任何级别编译确实去除死代码,这是很好的。 不过我很好奇,所以我试图做同样的有以下程序:
namespace {
void foo() { std::cout << "Foo!" << std::endl; }
void bar() { std::cout << "Bar!" << std::endl; }
}
int
main()
{
foo();
return 0;
}
这里的想法是看到Rob的解决方案是否实际上与模板特。 事实证明,以优化编译上面的代码上elides接通的未使用定义bar()
从可执行。 如此看来,虽然他的回答解决了我的眼前问题,但并没有解释为什么不使用的模板专门在所有编译。
有谁知道,从标准的相关片段,可以解释这一点? 我一直以为只有在使用生成的模板,但也许事实并非如此全特...