据我所知,存在新的 extern 模板功能以加快编译和链接时间。我正在尝试在(静态)库中使用它,据我所知它应该可以工作,因为 Bjarne Stroustrup's C++11 FAQ明确提及图书馆。
我有一个头文件,其中包含一些内容
template <typename T>
class Foo {
// Definitions of the methods
};
extern template class Foo<int>;
和一个实现文件
#include "Foo.hpp"
template class Foo<int>;
这些用于构建静态库libfoo
,然后链接到相应的单元测试FooTest
。然后,对于在测试中调用 Foo 对象的每个方法,链接都会给我 undefined symbol 错误。
我在这里做什么/做错了什么?
最佳答案
使用您的 github 代码,我可以使用 GCC 5.0 或 Clang 3.4 重现它,但不能使用 Clang 3.6(从 svn 构建)。
失败时Foo.cpp.o
不包含 qux::Foo<int, 2ul>::Foo(int const&)
的定义
$ nm -C Foo.cpp.o
U qux::Foo<int, 2ul>::Foo(int const&)
0000000000000000 W qux::Foo<int, 2ul>::Foo()
U qux::Foo<int, 2ul>::Foo(int const&)
0000000000000000 W qux::Foo<int, 2ul>::Foo()
0000000000000000 W qux::Foo<int, 2ul>::operator[](unsigned long) const
0000000000000000 W std::array<int, 2ul>::operator[](unsigned long) const
0000000000000000 W std::__array_traits<int, 2ul>::_S_ref(int const (&) [2], unsigned long)
但是使用 Clang 3.6 中定义了该符号
$ nm -C Foo.cpp.o
0000000000000000 W qux::Foo<int, 2ul>::Foo(int const&)
0000000000000000 W qux::Foo<int, 2ul>::Foo()
0000000000000000 W qux::Foo<int, 2ul>::Foo(int const&)
0000000000000000 W qux::Foo<int, 2ul>::Foo()
0000000000000000 n qux::Foo<int, 2ul>::Foo(int const&)
0000000000000000 n qux::Foo<int, 2ul>::Foo()
0000000000000000 W qux::Foo<int, 2ul>::operator[](unsigned long) const
0000000000000000 W std::array<int, 2ul>::operator[](unsigned long) const
0000000000000000 W std::__array_traits<int, 2ul>::_S_ref(int const (&) [2], unsigned long)
0000000000000000 W std::array<int, 2ul>::end()
0000000000000000 W std::array<int, 2ul>::data()
0000000000000000 W std::array<int, 2ul>::begin()
0000000000000000 W int* std::__addressof<int>(int&)
我不确定是什么问题,可能是 Clang 的一个错误,现在已经修复了,但奇怪的是 GCC 也有同样的错误。
导致问题的函数使用了 C++14 的宽松 constexpr 规则(在 constexpr 函数中循环),因此我认为这是编译器在实现该新功能时的错误。
关于c++ - 静态库中带有外部模板的 undefined symbol ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27425943/