假设我有以下代码片段:
template <class T>
class Bar
{
// static_assert(sizeof(T) > 0); // (1)
public:
void method()
{
static_assert(sizeof(T) > 0); // (2)
}
};
class Foo; // (3)
template class Bar<Foo>; // (4)
class Foo{}; // (5)
如果我们取消注释第 (1) 行,我们会得到一个编译时错误“不完整类型 T”,并且似乎很清楚:class Bar
实例化是由 (4) 启动的,而此时class Foo
仅由 (3) 前向声明尚未由 (5) 定义。
但是如果第(1)行被注释掉了,那么这段代码编译没有错误,这让我很困惑:(4)是一个显式的模板实例化定义,它强制编译器生成void method()
代码,第(2)行也应该生成同样的错误,因为 的定义Foo
稍后在 (5) 中进行。
我错过了什么,为什么片段中的代码会编译?
更新:代码在 GCC 8.2.0 和 MSVC 19.16.27025.1 下编译,但在 Clang 7.0.0 下它给出“不完整类型”错误。