Given this code:
//header.h
template <class T>
class Foo
{
public:
Foo(T t) : t(t) {}
T t;
};
//source1.cpp:
#include "header.h"
extern template class Foo<int>;
int main()
{
Foo<int> f(42);
}
By my understanding, this program should not link, since there should be no definition of class Foo<int> anywhere (extern template should prevent this). With VC++ 11 (Visual Studio 2012), this does however compile and link. In GCC, it doesn’t:
source1.cpp:(.text+0x15): undefined reference to `Foo<int>::Foo(int)'
If I link with source2.cpp however, it works (as I expect i should) :
#include "header.h"
template class Foo<int>;
According to this blog post, extern template should have been supported since VC10.
http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx
On a side note, is there a way to list the names in an object file on Windows / Visual Studio? On Linux I would do:
$ nm source1.o
U _ZN3FooIiEC1Ei <- "U" means that this symbol is undefined.
0000000000000000 T main
C++11 14.7.2/10 “Explicit instantiation” says:
And the constructor in you class template
Foo<T>is inline. VS2012 will work the way that you expect if you structure the header like so:so that the constructor isn’t inline.
The paragraph from the standard I quoted above does include the following note:
Looking at the assembly code created when the ctor is inlined, an out-of-line copy of the ctor is placed in the object file (even though the ctor is never even called if you compile the example with optimizations on), so MSVC doesn’t appear to be following the intent of the standard. However, notes are not normative, so I believe that MSVC’s behavior is conforming.
Regarding your side question about dumping symbols from object files built with MSVC, you can use the
dumpbinutility:When compiling the example with the non-inline constructor:
Compiling the example with the ctor inlined: