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

2024-04-29

考虑这个例子 https://godbolt.org/z/JQK_tu:

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中依赖名称和函数模板实例化的绑定规则和查找规则,但都无法解释这里发生的情况。


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

[温度点]/8 http://eel.is/c++draft/temp.point#8阅读,编辑掉不相关的部分:

函数模板 [...] 的特化可以在翻译单元内具有多个实例化点,并且除了上述实例化点之外,对于在翻译单元内具有实例化点的任何此类特化,结束翻译单元的点也被认为是实例化点。 [...] 如果两个不同的实例化点根据单一定义规则赋予模板专门化不同的含义,则程序格式错误,无需诊断。

YeapImpl<X>有两个实例化点:在问题中的注释行和翻译单元的末尾调用它。在第一个实例化点,X不完整,这会导致函数体格式错误。在第二个实例化点中,X是完整的,使身体结构良好。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么即使实际类型直到最后才定义,依赖名称也可以被认为是完整的 的相关文章

随机推荐