在Visual C ++中有extern模板的bug吗? [英] Is there a bug with extern template in Visual C++?

查看:160
本文介绍了在Visual C ++中有extern模板的bug吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定此代码:

//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);
}



根据我的理解,这个程序不应该链接,因为应该没有定义类Foo 任何地方( extern template 应该防止这种情况)。使用VC ++ 11(Visual Studio 2012),这不会编译和链接。在GCC中,它不会:

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)'



如果我与source2.cpp链接,我希望我应该):

If I link with source2.cpp however, it works (as I expect i should) :

#include "header.h"
template class Foo<int>;

根据这篇博文,extern模板应该自VC10以来一直支持。
http://blogs.msdn.com /b/vcblog/archive/2011/09/12/10209291.aspx

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

在旁注中,是否有一种方法可以列出对象文件在Windows / Visual Studio?在Linux上我会这样做:

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显式实例化说:

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:


[注意:意图是,作为
的主题的内联函数显式实例化声明仍然是隐式的
在使用odr时被实例化(3.2),使得主体可以被认为是
用于内联,但是在翻译单元中不会生成内联函数
的超出行的副本。 - end 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 ]

查看在ctor内联时创建的汇编代码,ctor的离线副本放置在目标文件中(即使ctor从来没有被调用,如果你使用优化编译示例),所以MSVC似乎没有遵循标准的意图。但是,注释不是规范性的,所以我相信MSVC的行为是符合的。

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.

使用MSVC构建的对象文件,可以使用 dumpbin 实用程序:

Regarding your side question about dumping symbols from object files built with MSVC, you can use the dumpbin utility:

构造函数:

dumpbin /symbols test.obj

...

008 00000000 UNDEF  notype ()    External     | ??0?$Foo@H@@QAE@H@Z (public: __thiscall Foo<int>::Foo<int>(int))
             ^^^^^
...

使用ctor内联示例编译示例:

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))
             ^^^^^

这篇关于在Visual C ++中有extern模板的bug吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆