将它放在名为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"
#ifndef SOMETHING
,然后使用t.hpp
来保护= default
中的非隐式声明。但是在版本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确实引入了一个带有/home/barmistias/Desktop
的默认构造函数而不是多参数的默认参数,但同样,直到GCC 6.1我的问题才出现。