模板的外部模板参数化为incompete类型

Smi*_*les 8 c++ templates forward-declaration incomplete-type c++11

一个可编辑的例子:

main.cpp中

#include "test.h"

int main(int argc, char* argv[]) {
    auto myPtr = std::unique_ptr<MyClass>(getMyPtr());
}
Run Code Online (Sandbox Code Playgroud)

test.h

#ifndef TEST_H
#define TEST_H

#include <memory>

class MyClass;
extern template class std::unique_ptr<MyClass>;
MyClass* getMyPtr();

#endif
Run Code Online (Sandbox Code Playgroud)

TEST.CPP

#include "test.h"

class MyClass {};
template class std::unique_ptr<MyClass>;
MyClass* getMyPtr() { return new MyClass; }
Run Code Online (Sandbox Code Playgroud)

g ++ 4.9.2抱怨

In file included from c:/devel/mingw32/i686-w64-mingw32/include/c++/memory:81:0,
                 from main.cpp:4:
c:/devel/mingw32/i686-w64-mingw32/include/c++/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = MyClass]':
c:/devel/mingw32/i686-w64-mingw32/include/c++/bits/unique_ptr.h:236:16:   required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = MyClass; _Dp = std::default_delete<MyClass>]'
main.cpp:64:53:   required from here
c:/devel/mingw32/i686-w64-mingw32/include/c++/bits/unique_ptr.h:74:22: error: invalid application of 'sizeof' to incomplete type 'MyClass'
  static_assert(sizeof(_Tp)>0,
                      ^
Run Code Online (Sandbox Code Playgroud)

即使MyClass在模板实例化时应该是可见的.为什么?

编辑: 在示例中修复了拼写错误.

Die*_*ühl 6

实例化声明的效果,即模板未隐式实例化的保证,不适用于inline根据14.7.2 [temp.explicit]第10段的函数:

除了内联函数,从其初始值或返回值(7.1.6.4)推导出类型的声明,文字类型的常量变量,引用类型的变量和类模板特化之外,显式实例化声明具有抑制隐式实例化的效果.他们所指的实体.[注意:意图是当使用odr(3.2)时,仍然会隐式实例化作为显式实例化声明主题的内联函数,以便可以考虑使用内联体,但是不需要外联副本内联函数的内容将在翻译单元中生成.-end note]

标准库显然可以自由声明其任何功能inline.也就是说,使用实例化声明不会影响使用标准库模板类定义的类型的要求(当然,除非另有说明).gcc std::unique_ptr<...>在此类模板的定义中定义了析构函数,使其隐式内联.以下是演示该问题的示例源:取决于是否DECL_ONY定义了编译器:

template <typename T>
struct foo
{
    ~foo()
#ifdef DECL_ONLY
        ;
#else
    { static_assert(sizeof(T), "defined!"); }
#endif
};

#ifdef DECL_ONLY
template <typename T>
foo<T>::~foo() { static_assert(sizeof(T), "defined!"); }
#endif

class MyClass;
extern template struct foo<MyClass>;

int main(int , char* []) {
    foo<MyClass> f;
}
Run Code Online (Sandbox Code Playgroud)

  • 我试图extern模板default_delete,得到相同的消息. (2认同)