给定这段代码:
//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);
}
根据我的理解,这个程序不应该链接,因为不应该有 class Foo<int>
的定义。任何地方( extern template
应该阻止这种情况)。然而,对于 VC++ 11 (Visual Studio 2012),这确实可以编译和链接。在 GCC 中,它不会:
source1.cpp:(.text+0x15): undefined reference to `Foo<int>::Foo(int)'
但是,如果我链接到 source2.cpp,它就可以工作(正如我所期望的那样):
#include "header.h"
template class Foo<int>;
根据这篇博文,extern template应该从VC10开始就支持了。 http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx
附带说明一下,有没有办法在 Windows/Visual Studio 的目标文件中列出名称?在 Linux 上我会这样做:
$ nm source1.o
U _ZN3FooIiEC1Ei <- "U" means that this symbol is undefined.
0000000000000000 T main
最佳答案
C++11 14.7.2/10“显式实例化”说:
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.
还有类模板中的构造函数Foo<T>
是内联的。如果您像这样构造 header ,VS2012 将按照您期望的方式工作:
//header.h
template <class T>
class Foo
{
public:
Foo(T t);
T t;
};
template <class T>
Foo<T>::Foo(T t) : t(t)
{
}
这样构造函数就不是内联的。
我上面引用的标准中的段落确实包含以下注释:
[ 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 ]
查看内联 ctor 时创建的汇编代码,ctor 的一个外联拷贝被放置在目标文件中(即使如果您编译带有优化的示例,ctor 甚至永远不会被调用),所以 MSVC 似乎没有遵循标准的意图。但是,注释不是规范的,所以我认为 MSVC 的行为是符合规范的。
关于从使用 MSVC 构建的目标文件中转储符号的附带问题,您可以使用 dumpbin
效用:
使用非内联构造函数编译示例时:
dumpbin /symbols test.obj
...
008 00000000 UNDEF notype () External | ??0?$Foo@H@@QAE@H@Z (public: __thiscall Foo<int>::Foo<int>(int))
^^^^^
...
使用内联构造函数编译示例:
00A 00000000 SECT4 notype () External | ??0?$Foo@H@@QAE@H@Z (public: __thiscall Foo<int>::Foo<int>(int))
^^^^^
关于c++ - Visual C++ 中的外部模板是否存在错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13613926/