【问题标题】:How to use "extern template" with a nested class which is used by a templated member in the same class?如何将“外部模板”与同一类中的模板化成员使用的嵌套类一起使用?
【发布时间】:2014-06-13 03:11:03
【问题描述】:

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

#include "pimpl_h.h"
class widget {
    class impl;
    pimpl<impl> m;
    // ...
};

实现如下所示:

#include "pimpl_impl.h"
class widget::impl {
    // ...
};

当使用此技术的类使用另一个 Pimpl 类进行自己的实现时,就会出现我试图解决的问题。它包含“pimpl_impl.h”,因此编译器(在我的情况下为 VC++ 2013)获得了另一个类的 pimpl &lt;impl&gt; 的具体模板的知识,并尝试隐式实例化它,这当然会导致编译错误。不知道那个类的实现。

为了解决这个问题,我在标头中使用了 C++ 11 的新“外部模板”功能:

#include "pimpl_h.h"
class widget {
    class impl;
    pimpl<impl> m;
    // ...
};
extern template pimpl<widget::impl>;

这应该保证只有我在提供widget::impl 实现的编译单元中的显式实例化会导致实际实例化。这编译没有问题,但 IntelliSense 显示错误:

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

我想不出任何其他方式。我的问题是:

在接受我的代码时 IntelliSense 是否错误而编译器是否正确?还是 VC++ 编译它而它不是有效的 C++ 只是巧合?

如果我的解决方案不是有效的 C++,我有什么替代方案?

【问题讨论】:

    标签: c++ c++11 templates


    【解决方案1】:

    我想这是我自己想出来的。在 §14.7.2.11 标准中说

    如果一个实体同时是显式实例化声明和显式实例化声明的主题 同一个翻译单元中的实例化定义,定义应遵循 声明。

    这可能是 IntelliSense 所指的。这就是我注意到错误消息“...无法遵循 explicit 实例化...”的地方。显然在任何地方都没有显式实例化,只有widget 的类定义中的隐式 实例化。所以我认为这是 IntelliSense 中的一个错误。在同一段内,标准说

    作为显式实例化声明主题的实体,同时也是 以否则会导致隐式实例化(14.7.1)的方式使用 翻译单元应该是一个明确的实例化定义的主题—— 在程序中的哪个位置;否则程序格式错误,不需要诊断。

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

    此时我也意识到我的解决方案对于我原来的问题实际上是矫枉过正的。我不想阻止 pimpl&lt;impl&gt; 的模板类 declarationdefinition 的隐式实例化,而只阻止里面的模板类 definition pimpl_impl.hextern template pimpl&lt;impl&gt; 抑制了两者,这解决了我的问题,但做得比必要的多。解决方案是用extern template 声明pimpl&lt;impl&gt; 的实际成员,并在以后显式实例化它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-06
      • 2016-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多