静态库中带有extern模板的未定义符号

时间:2014-12-11 15:06:10

标签: c++ templates extern c++14

据我所知,新的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对象的每个方法提供了未定义的符号错误。

我在做什么/出错?

1 个答案:

答案 0 :(得分:6)

使用你的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函数中循环),所以我认为这是编译器实现该新特性的一个错误。