Given this code:
//header.h
template
class Foo
{
public:
Foo(T t) : t(t) {}
T t;
};
//source1.cpp:
#include \"header.h\"
extern template
C++11 14.7.2/10 "Explicit instantiation" says:
Except for inline functions and class template specializations, explicit instantiation declarations have the effect of suppressing the implicit instantiation of the entity to which they refer.
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:
//header.h
template <class T>
class Foo
{
public:
Foo(T t);
T t;
};
template <class T>
Foo<T>::Foo(T t) : t(t)
{
}
so that the constructor isn't inline.
The paragraph from the standard I quoted above does include the following note:
[ Note: The intent is that an inline function that is the subject of an explicit instantiation declaration will still be implicitly instantiated when odr-used (3.2) so that the body can be considered for inlining, but that no out-of-line copy of the inline function would be generated in the translation unit. — end 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 dumpbin
utility:
When compiling the example with the non-inline constructor:
dumpbin /symbols test.obj
...
008 00000000 UNDEF notype () External | ??0?$Foo@H@@QAE@H@Z (public: __thiscall Foo<int>::Foo<int>(int))
^^^^^
...
Compiling the example with the ctor inlined:
00A 00000000 SECT4 notype () External | ??0?$Foo@H@@QAE@H@Z (public: __thiscall Foo<int>::Foo<int>(int))
^^^^^