如何将模板实例化导出为非弱?

How to export template instantiation as non weak?

C++ 模板函数导出为弱符号以解决单一定义规则 ()。在为每个用例显式实例化函数的情况下,有没有办法将符号导出为非弱?

示例用例:

// foo.hpp
template<typename T>
void foo();

// All allowed instantiations are explicitly listed.
extern template void foo<int>();
extern template void foo<short>();
extern template void foo<char>();
// foo.cpp
template<typename T>
void foo()
{
  // actual implementation
}

// All explicit instantiations.
template void foo<int>();
template void foo<short>();
template void foo<char>();

当我用 GCC 或 ICC 编译上面的代码时,它们被标记为弱:

$ nm foo.o
                 U __gxx_personality_v0
0000000000000000 W _Z3fooIcEvv
0000000000000000 W _Z3fooIiEvv
0000000000000000 W _Z3fooIsEvv

有什么办法可以避免吗?因为它们实际上是确定的,所以我不希望它们成为替代的候选对象。

objcopy 支持 --weaken 选项,但你想要相反的选项。

它也支持 --globalize-symbol,但似乎对弱符号没有影响:

gcc -c t.cc
readelf -Ws t.o | grep _Z3fooI

    14: 0000000000000000     7 FUNC    WEAK   DEFAULT    7 _Z3fooIiEvv
    15: 0000000000000000     7 FUNC    WEAK   DEFAULT    8 _Z3fooIsEvv
    16: 0000000000000000     7 FUNC    WEAK   DEFAULT    9 _Z3fooIcEvv

objcopy -w --globalize-symbol _Z3fooI* t.o t1.o && 
readelf -Ws t1.o | grep _Z3fooI

    14: 0000000000000000     7 FUNC    WEAK   DEFAULT    7 _Z3fooIiEvv
    15: 0000000000000000     7 FUNC    WEAK   DEFAULT    8 _Z3fooIsEvv
    16: 0000000000000000     7 FUNC    WEAK   DEFAULT    9 _Z3fooIcEvv

不被吓倒,我们可以先本地化符号,然后再全球化:

objcopy -w -L _Z3fooI* t.o t1.o &&
objcopy -w --globalize-symbol _Z3fooI* t1.o t2.o &&
readelf -Ws t2.o | grep _Z3fooI

    14: 0000000000000000     7 FUNC    GLOBAL DEFAULT    7 _Z3fooIiEvv
    15: 0000000000000000     7 FUNC    GLOBAL DEFAULT    8 _Z3fooIsEvv
    16: 0000000000000000     7 FUNC    GLOBAL DEFAULT    9 _Z3fooIcEvv

瞧:符号现在已被严格定义。

The problem I am trying to solve is that the link time is too slow and I want to reduce the work of the linker to the minimum.

如果这会使链接器做更少的工作(我对此表示怀疑),我会认为这是链接器中的错误——如果符号被定义一次,那么该定义是否对链接器来说无关紧要强或弱。