模板参数类型被编译器视为完整的,但其定义尚不可见
Template parameter type is treated as complete by the compiler, but its definition isn't yet visible
假设我有以下代码片段:
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),我们会得到一个编译时错误 "incomplete type T",而且似乎很清楚:class Bar
实例化是由 (4) 启动的,在那点 class Foo
仅由 (3) 向前声明,尚未由 (5) 定义。
但是如果第 (1) 行被注释掉,那么这段代码编译没有错误,这让我感到困惑: (4) 是一个显式模板实例化定义,它强制编译器生成 void method()
代码和第 (2) 行也应该产生相同的错误,因为 Foo
的定义稍后在 (5).
中进行
我错过了什么,为什么代码片段中的代码可以编译?
UPDATE:代码在 GCC 8.2.0 和 MSVC 19.16.27025.1 下编译,但在 Clang 7.0.0 下会出现 "incomplete type" 错误。
按照标准,在隐式实例化过程中,只实例化成员函数的声明,而不实例化它们的定义。
[temp.inst]/2 - The implicit instantiation of a class template specialization causes
- the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends ...
但是对于显式实例化,它并没有说同样的话。整个 class 被实例化,这意味着它实例化了 method()
的定义,此时 Foo
还不完整。
[temp.explicit]/11 - An explicit instantiation definition that names a class template specialization explicitly instantiates the class template specialization and is an explicit instantiation definition of only those members that have been defined at the point of instantiation.
clang 拒绝代码。
假设我有以下代码片段:
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),我们会得到一个编译时错误 "incomplete type T",而且似乎很清楚:class Bar
实例化是由 (4) 启动的,在那点 class Foo
仅由 (3) 向前声明,尚未由 (5) 定义。
但是如果第 (1) 行被注释掉,那么这段代码编译没有错误,这让我感到困惑: (4) 是一个显式模板实例化定义,它强制编译器生成 void method()
代码和第 (2) 行也应该产生相同的错误,因为 Foo
的定义稍后在 (5).
我错过了什么,为什么代码片段中的代码可以编译?
UPDATE:代码在 GCC 8.2.0 和 MSVC 19.16.27025.1 下编译,但在 Clang 7.0.0 下会出现 "incomplete type" 错误。
按照标准,在隐式实例化过程中,只实例化成员函数的声明,而不实例化它们的定义。
[temp.inst]/2 - The implicit instantiation of a class template specialization causes
- the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends ...
但是对于显式实例化,它并没有说同样的话。整个 class 被实例化,这意味着它实例化了 method()
的定义,此时 Foo
还不完整。
[temp.explicit]/11 - An explicit instantiation definition that names a class template specialization explicitly instantiates the class template specialization and is an explicit instantiation definition of only those members that have been defined at the point of instantiation.
clang 拒绝代码。