G ++生成用于未使用的模板特码?(G++ generates code for unused te

2019-08-16 15:32发布

在有些系列化代码的项目我的工作我有一个类型,其大小是依赖于编译器。 为了解决这个问题,我决定用一个模板专业化,伟大的工程。 一切都在编译时得到解决。 该代码看起来是这样一点点(不是真正的代码,只是一个例子):

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()从可执行。 如此看来,虽然他的回答解决了我的眼前问题,但并没有解释为什么不使用的模板专门在所有编译。

有谁知道,从标准的相关片段,可以解释这一点? 我一直以为只有在使用生成的模板,但也许事实并非如此全特...

Answer 1:

在您的示例模板特是具有外部链接的功能。 编译器无法知道,他们不会从其他翻译单元被调用。

在我的g ++ 4.7.2 Ubuntu系统,将所述模板为匿名命名空间和与编译-O3防止产生未使用的功能。

同样,在声明函数模板static了预期的效果。



Answer 2:

这是一个特殊的问题。 我看着它一点点,这个问题是无关的模板特殊化。 我想克++没有,在默认情况下,未使用的带符号。 这是有道理的情况下,你以后想你的输出连接到另一个程序。

不过,也有可以使用剥离未使用符号的命令行选项。 有关详细信息,请参阅这篇文章:

如何使用GCC和LD删除未使用的C / C ++的符号?

而且在这里看到

使用GCC发现无法访问功能(“死码”)

和这里

死代码检测传统的C / C ++项目

只是尝试了这一点,我修改了代码如下:

#include <iostream>

void junk_function() {
    std::cout<<"test" << std::endl;    
}

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;
}

然后存储在此代码sp.cpp。 第一,

g++ -Os sp.cpp -o sp
nm sp

而得到这个(请注意,我删除了一堆的可读性符号):

0804879a T _Z13junk_functionv
080487b8 T _Z16special_functionILi4EEvv
080487f5 T _Z16special_functionILi8EEvv

看来两个未使用的符号存在。 我也试过-O1,-O2,-O3,并得到了相同的。

下一个:

g++ -Os -fdata-sections -ffunction-sections sp.cpp -o sp -Wl,--gc-sections
nm sp

而得到这个:

0804875a T _Z16special_functionILi4EEvv

而已。 所以它看起来像你只需要通过正确的论点告诉G ++剥离未使用的符号。 在Mac上,我想他们有-dead_strip的选择,但我不知道为什么它不以g ++工作(即使它是在手册页提及。诚然,我并没有深入到这一点,所以有可能是印刷精美,我错过了)。

我认为,VISUAL C ++的连接带默认情况下,当你联系,但我没有测试。 也许别人可以插入内容。



文章来源: G++ generates code for unused template specializations?