为什么即使直到最后才定义实际类型,也可以将依赖名称视为完整

Why can a dependent name be considered as complete even if the actual type is not defined until the very end

本文关键字:依赖 也可以 直到最后 定义 类型 为什么      更新时间:2023-10-16

考虑这个例子:

template <class T>
void Yeap(T);
int main() {
Yeap(0);
return 0;
}
template <class T>
void YeapImpl();
struct X;
template <class T>
void Yeap(T) {
YeapImpl<X>(); // pass X to another template
}
template <class T>
void YeapImpl() {
T().foo();
}
struct X {
void foo() {}
};

请注意,struct X直到最后才定义。我曾经认为所有 odr 使用的名称在实例化时都必须是完整的。但是在这里,编译器如何在定义之前将其视为完整类型?

我已经检查了 cppreference 中依赖名称和函数模板实例化的绑定规则和查找规则,但它们都无法解释这里发生了什么。

我相信这个程序格式不正确,不需要诊断。

[temp.point]/8 读取,编辑掉不相关的部分:

函数模板的专用化在翻译单元中可能具有多个实例化点,除了上述实例化点

之外,对于在翻译单元内具有实例化点的任何此类专用化,翻译单元的末尾也被视为实例化点。[...]如果两个不同的实例化点根据一个定义规则赋予模板专用化不同的含义,则程序格式不正确,无需诊断。

YeapImpl<X>有两个实例化点:在问题中的注释行和翻译单元的末尾调用它。在实例化的第一点中,X是不完整的,这将使函数的主体格式不正确。在实例化的第二点,X是完整的,这使得身体形成良好。

这两个专业具有[非常]不同的含义。

相关文章: