以下程序是否格式错误?如果是这样,这里进行诊断有什么问题吗?
template <typename T> struct A { int a{sizeof(T)}; };
int main() { sizeof(A<void>); }
Run Code Online (Sandbox Code Playgroud)
Clang 为该代码生成以下专业化 ( clang++ -std=c++20 -Xclang -ast-print -fsyntax-only main.cpp):
template <typename T> struct A {
int a {sizeof(T)};
};
template<> struct A<void> {
int a;
};
int main() {
sizeof(A<void>);
}
Run Code Online (Sandbox Code Playgroud)
对于类模板来说,里面的定义只有在使用的时候才会被实例化。在示例中:
template <typename T>
struct A {
int a{sizeof(T)};
};
Run Code Online (Sandbox Code Playgroud)
sizeofto的应用A<void>只需要实例化A并了解数据成员的类型。该表达式sizeof(T)是类型依赖的T并且不是必需的,因此 GCC 和 Clang 都不会在这里实例化它。这是允许的:
类模板特化的隐式实例化导致
- [...]的隐式实例化
类模板特化的隐式实例化不会导致类成员函数的默认参数或 noexcept 说明符的隐式实例化。
- [临时实例]/3
本段中没有列出非静态数据成员的初始化程序,因此到目前为止我们是安全的。该成员实际上将在以下情况下被实例化:
[...] 当在需要成员定义存在的上下文中引用专门化时,或者如果成员定义的存在影响程序的语义,则隐式实例化成员的专门化;
- [临时实例]/4
的定义a及其初始值设定项不必实例化sizeof(A<void>),因为它不需要存在并且不会影响程序的语义。
但是,如果您创建了类型为 的变量A<void>,则编译器将需要实例化 中的默认成员初始值设定项A,从而使程序格式错误:
int main() {
sizeof(A<void>); // OK up to this point
A<void> a; // ill-formed (GCC issues warning, Clang issues error)
}
Run Code Online (Sandbox Code Playgroud)
-Xclang -ast-print -fsyntax-onlyRun Code Online (Sandbox Code Playgroud)template<> struct A<void> { int a; };
请注意,您所看到的只是 clang 迄今为止实例化的内容的表示。生成的语法树a根本不包含默认成员初始值设定项。这并不是A<void>一次完全实例化的内容(包括所有成员)的表示,而只是 clang 到目前为止所知道的内容的表示。