把它放在一个名为 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 SOMETHING
在t.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 才出现我的问题。