Is there a bug with extern template in Visual C++?

前端 未结 1 1613
一向
一向 2020-12-09 13:21

Given this code:

//header.h
template 
class Foo
{
public:
  Foo(T t) : t(t) {}
  T t;
};

//source1.cpp:
#include \"header.h\"
extern template         


        
相关标签:
1条回答
  • 2020-12-09 14:05

    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))
                 ^^^^^
    
    0 讨论(0)
提交回复
热议问题