C++ 如何使用;“外部模板”;是否使用同一类中的模板成员使用的嵌套类?

C++ 如何使用;“外部模板”;是否使用同一类中的模板成员使用的嵌套类?,c++,c++11,templates,C++,C++11,Templates,首先,一些上下文:我试图用Herb Sutter在他的解决方案中提出的方式来使用Pimpl习语。这在头文件中看起来像这样: #include "pimpl_h.h" class widget { class impl; pimpl<impl> m; // ... }; 当使用此技术的类使用另一个Pimpl类作为自己的实现时,就会出现我试图解决的问题。它包括“pimpl_impl.h”,因此编译器(在我的例子中是VC++2013)了解另一个类的pimpl的具体

首先,一些上下文:我试图用Herb Sutter在他的解决方案中提出的方式来使用Pimpl习语。这在头文件中看起来像这样:

#include "pimpl_h.h"
class widget {
    class impl;
    pimpl<impl> m;
    // ...
};
当使用此技术的类使用另一个Pimpl类作为自己的实现时,就会出现我试图解决的问题。它包括“pimpl_impl.h”,因此编译器(在我的例子中是VC++2013)了解另一个类的
pimpl
的具体模板,并尝试隐式实例化它,这当然会导致编译错误,因为它不知道该类的实现

为了解决这一问题,我在标题中使用了C++ 11的新的“外部模板”特性:

#include "pimpl_h.h"
class widget {
    class impl;
    pimpl<impl> m;
    // ...
};
extern template pimpl<widget::impl>;
由于“extern模板”不能在类声明中使用,因此我无法编写

#include "pimpl_h.h"
class widget {
    class impl;
    extern template pimpl<impl>;
    pimpl<impl> m;
    // ...
};
#包括“pimpl_h.h”
类小部件{
类impl;
外部模板pimpl;
皮姆;
// ...
};
我想不出别的办法了。我的问题是:

IntelliSense接受我的代码是错误的,而编译器是正确的吗?或者VC++编译这是不是巧合,它不是有效的C++?
<如果我的解决方案不是有效的C++,我还有什么选择?

我想我自己已经明白了。在§14.7.2.11中,本标准规定:

如果实体是显式实例化声明和显式 实例化定义在同一翻译单元中,定义应遵循 声明

这可能就是IntelliSense所指的。这就是我注意到错误消息说“…不能遵循显式实例化…”。显然,任何地方都没有显式实例化,只有
小部件的类定义中的隐式实例化。所以我假设这是IntelliSense内部的一个bug。在同一段中,标准说

一种实体,它是显式实例化声明的主题,也是 使用的方式可能会导致中的隐式实例化(14.7.1) 翻译单元应为明确的实例化定义的主题- 在程序中的什么位置;否则,程序格式不正确,不需要诊断

它不需要(潜在的)隐式实例化和显式实例化声明的任何特定顺序

在这一点上,我也意识到,我的解决方案实际上是对我的原始问题的过度杀伤力。我不想阻止
pimpl
的模板类声明和定义的隐式实例化,只想阻止
pimpl\u impl.h
中的模板类定义的隐式实例化。
extern模板pimpl
同时抑制了这两个选项,这解决了我的问题,但做了更多必要的工作。解决方案是使用
extern template
声明
pimpl
的实际成员,并在以后显式实例化它们

Error: 'extern template' cannot follow explicit instantiation of class "pimpl<widget::impl>"
#include "pimpl_h.h"
class widget {
    class impl;
    extern template pimpl<impl>;
    pimpl<impl> m;
    // ...
};