首先,一些背景信息:我尝试以 Herb Sutter 在他的解决方案中介绍的方式使用 Pimpl 习语。得到了#101 http://herbsutter.com/gotw/_101/。这在头文件中看起来像这样:
#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 <impl>
另一个类并尝试隐式实例化它,这当然会导致编译错误,因为它不知道该类的实现。
为了解决这个问题,我在头文件中使用了 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++,我有哪些替代方案?