具有不完整类型的类模板实例化

Dmi*_*try 3 c++ templates

以下程序是否格式错误?如果是这样,这里进行诊断有什么问题吗?

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)

Jan*_*tke 6

对于类模板来说,里面的定义只有在使用的时候才会被实例化。在示例中:

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-only

template<> struct A<void> {
   int a;
};
Run Code Online (Sandbox Code Playgroud)

请注意,您所看到的只是 clang 迄今为止实例化的内容的表示。生成的语法树a根本不包含默认成员初始值设定项。这并不是A<void>一次完全实例化的内容(包括所有成员)的表示,而只是 clang 到目前为止所知道的内容的表示。