Reputation: 1247
As far as I know the new extern template functionality exists to speed up compile and link times. I am trying to use this in a (static) library, which as far as I know should work, since Bjarne Stroustrup's C++11 FAQ explicitly mentions libraries.
What I have is a header file containing something along the lines of
template <typename T>
class Foo {
// Definitions of the methods
};
extern template class Foo<int>;
And an implementation file
#include "Foo.hpp"
template class Foo<int>;
These are used to build a static library libfoo
, which is then linked to the corresponding unit test FooTest
. The linking then gives me undefined symbol errors for every method called on Foo objects in the test.
What am I doing/getting wrong here?
Upvotes: 2
Views: 665
Reputation: 171263
Using your github code I can reproduce it with GCC 5.0 or Clang 3.4 but not Clang 3.6 (built from svn).
When it fails Foo.cpp.o
does not contain a definition of 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)
But using Clang 3.6 that symbol is defined in
$ 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&)
I'm not sure what the problem is, it might be a bug in Clang which has now been fixed, but it's strange that GCC has the same bug.
The function that causes the problem uses C++14's relaxed constexpr rules (looping in a constexpr function), so I assume it's a bug in the compilers' implementation of that new feature.
Upvotes: 6