为什么即使直到最后才定义实际类型,依赖名称也可以被认为是完整的
Why can a dependent name be considered as complete even if the actual type is not defined until the very end
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中依赖名称和函数模板实例化的绑定规则和查找规则,但是其中none可以解释这里发生的事情。
我认为这个程序格式错误,不需要诊断。
[temp.point]/8阅读,删去无关部分:
A specialization for a function template [...] may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. [...] If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.
YeapImpl<X>
有两个实例化点:在问题的注释行和翻译单元末尾调用它的地方。在实例化的第一个点,X
是不完整的,这会使函数的主体格式错误。在实例化的第二个点,X
是完整的,这使得正文是合式的。
这两个专业有[非常]不同的含义。
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中依赖名称和函数模板实例化的绑定规则和查找规则,但是其中none可以解释这里发生的事情。
我认为这个程序格式错误,不需要诊断。
[temp.point]/8阅读,删去无关部分:
A specialization for a function template [...] may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. [...] If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.
YeapImpl<X>
有两个实例化点:在问题的注释行和翻译单元末尾调用它的地方。在实例化的第一个点,X
是不完整的,这会使函数的主体格式错误。在实例化的第二个点,X
是完整的,这使得正文是合式的。
这两个专业有[非常]不同的含义。