4

把它放在一个名为 t.hpp 的文件中:

#include <unordered_map>

extern template class std::unordered_map<int, int>;

std::unordered_map<int, int> getMap();

这在 t.cpp 中:

#include "t.hpp"

std::unordered_map<int, int> getMap()
{
    return std::unordered_map<int, int>();
}

template class std::unordered_map<int, int>;

然后构建它(在 Linux 上):

g++ -std=c++11 -shared -fPIC -o t.so t.cpp

然后查看共享对象中的构造函数:

objdump --syms --demangle t.so | grep '::unordered_map()'

如果你用 GCC 4.9 编译它应该什么都不显示。对于 GCC 5.1 或 5.3,它应该显示如下内容:

8a w F .text 1b std::unordered_map<int, int>::unordered_map()

但在 GCC 6.1 中,它显示如下:

0 *UND* 0 std::unordered_map<int, int>::unordered_map()

这意味着地图的默认构造函数不会在共享对象中发出,尽管它需要发出。这会导致稍后在可执行文件中使用共享对象时链接失败。

如果您使用-O1或更高版本进行编译,问题就会消失(构造函数是内联的)。

中的显式模板实例化似乎t.cpp被 中的非隐式声明所禁止t.hpp。我想出的一种解决方法是#define SOMETHINGt.cpp之前#include "t.hpp"使用in#ifndef SOMETHING来保护t.hpp. 但在版本 6 之前的 GCC 中,这不是必需的,我不确定它是否应该如此。

这是 GCC 6.1 中的错误吗?还是代码错了?

编辑:我发现了这个错误:https ://gcc.gnu.org/bugzilla/show_bug.cgi?id=57728这可能是相关的,但它是针对 GCC 4.8 报告的,而我的问题直到 6.1 才出现。GCC 5.1 vs 4.9 确实引入了一个空默认构造函数,= default而不是多参数的默认参数,但同样,直到 GCC 6.1 才出现我的问题。

4

0 回答 0