GCC(8.3,9.1),Clang(7、8)和MSVC(19.20)的不同之处在于它们编译此代码的能力:
struct C;
template<typename T> struct S {
void foo() {
// C2 c;
C c;
}
};
class C {};
int main() {
S<int> s;
s.foo();
return 0;
}
GCC和MSVC接受它,而Clang拒绝它。即使我自己将foo
用作模板和/或根本不调用它,Clang也会拒绝它。
我的理解是,foo
除非被调用,否则不会被实例化,而是在被调用时被实例化。到此,C
完成,并且代码应编译。这是海湾合作委员会的理由吗?
请注意,如果未调用foo
,即使我将C
替换为C2
中未声明的foo
,MSVC也会接受代码-在这种情况下,它会似乎只是在检查函数体在语法上是否正确。
根据标准,哪种行为是正确的?如果是Clang,为什么标准会禁止GCC提供的灵活性?
答案 0 :(得分:12)
由于[temp.res]/8,这是错误的格式,无需诊断:
该程序格式不正确,如果满足以下条件,则无需进行诊断:
- [...]
- 由于模板不依赖于模板参数或[...]
,因此,紧随其定义的模板的假设实例化将不正确。- [...]
因此整个程序很糟糕,但是不需要实现即可对其进行诊断。 Clang可以,这对clang很好,而gcc和MSVC却不可以,这没错。