本文介绍了G ++为未使用的模板专业化生成代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
在我正在处理的一个项目的一些序列化代码中,我有一个类型,它的大小依赖于编译器。为了解决这个问题,我决定使用模板专业化,这很好。一切都在编译时解决。代码看起来有点像这样(不是真正的代码,只是一个例子):
模板< int size>
void
special_function()
{
std :: cout<< 没有专门调用:<<大小<<的std :: ENDL;
}
模板<>
void
special_function< 4>()
{
std :: cout<< dword<<的std :: ENDL;
}
模板<>
void
special_function< 8>()
{
std :: cout<< qword<<的std :: ENDL;
main()
{
special_function< sizeof(int)>();
返回0;
$ b在我的32位系统上,执行上述程序输出 dword
,如预期。但是,这样做的关键,不仅仅是做 if(sizeof(int)== 4){...} else if ...
是我的希望编译器只能为适当的函数生成代码。由于 special_function< 4>
是这个程序中唯一调用的,所以我期望它是由编译器生成的唯一一个(在这种情况下,gcc 4.1.2,x86 Linux)。
但这不是观察到的行为。
虽然它确实有效,但每个代码尽管没有被使用,但是模板专业化被生成。但是,不会生成泛型定义。
我应该提到,这是一步式编译,而不是汇编成中间目标文件,然后是链接。在这种情况下,推迟将死代码移除到链接阶段似乎很自然,我知道连接器并不总是非常擅长这一点。
有人知道什么是继续?有没有我在这里失踪的模板专业的细微之处? Lord知道恶魔在C ++的细节中。
编辑:既然已经提到过,这种行为同时发生在-O3和-Os上。
EDIT2:Rob建议将函数放入匿名命名空间。这样做并编译任何级别的优化确实会删除死代码,这很好。但我很好奇,所以我试着用下面的程序做同样的事情:
namespace {
void foo() {std :: cout<< 富! <<的std :: ENDL; }
void bar(){std :: cout<< 酒吧! <<的std :: ENDL; }
}
int
main()
{
foo();
返回0;
}
这里的想法是看Rob的解决方案是否真的与模板特化有关。事实证明,开启优化后编译的上述代码将从可执行文件中删除未使用的 bar()
定义。因此,虽然他的答案解决了我眼前的问题,但它并不能解释为什么模板专门化不被使用。
有人知道标准中的相关片段可以解释这一点吗?我一直认为模板只是在使用时生成的,但也许这不是完全专业化的模式。
模板专业化在你的例子中是具有外部链接的功能。编译器无法知道它们不会被另一个翻译单元调用。
在我的g ++ 4.7.2 Ubuntu系统中,将模板放入匿名名称空间并编译无论是 -O3
还是 -O4
都会阻止未使用的函数生成。
同样,声明函数模板 static
也能达到理想的效果。
In a bit of serialization code for a project I'm working on I have a type whose size is compiler dependent. In order to deal with this, I decided to use a template specialization, which works great. Everything is resolved at compile time. The code looks a little bit like this (not the real code, just an example):
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;
}
On my 32-bit system, executing the above program outputs dword
, as expected. But the whole point of doing it this way and not just doing if (sizeof(int) == 4) { ... } else if ...
is that I had hoped that the compiler would only produce code for the appropriate function. Since special_function<4>
is the only one called in this program, I expected it to be the only one generated by the compiler (gcc 4.1.2 in this case, on x86 Linux).
But that is not the observed behavior.
While it indeed works, the code for each template specialization is generated despite not being ever used. The generic definition is not generated, however.
I should mention that this is a one-step compilation, not a compilation into intermediary object files followed by a link. In that case it would seem natural to defer dead code removal to the link stage, and I know that linkers are not always terribly good at this.
Does anyone know what is going on? Is there a subtlety of template specialization I'm missing here? Lord knows the devil is in the details with C++.
EDIT: Since it's been mentioned, this behavior occurs with both -O3 and -Os.
EDIT2: Rob below suggested putting the functions in an anonymous namespace. Doing so and compiling with any level of optimization does indeed remove the dead code, which is good. But I was curious, so I tried doing the same with the following program:
namespace {
void foo() { std::cout << "Foo!" << std::endl; }
void bar() { std::cout << "Bar!" << std::endl; }
}
int
main()
{
foo();
return 0;
}
The idea here is see whether or not Rob's solution is actually related to template specializations. As it turns out, the above code compiled with optimizations turned on elides the unused definition of bar()
from the executable. So it seems that while his answer solves my immediate problem, it doesn't explain why template specializations that aren't used are compiled at all.
Does anyone know of a relevant snippet from the standard that would explain this? I always thought templates were generated only on use, but perhaps this is not so for full specializations ...
解决方案
The template specializations in your example are functions with external linkage. The compiler cannot know that they won't be called from another translation unit.
On my g++ 4.7.2 Ubuntu system, placing the templates into an anonymous namespace and compiling with either -O3
or -O4
prevented the unused function from being generated.
Similarly, declaring the function template static
had the desired effect.
这篇关于G ++为未使用的模板专业化生成代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!