在类模板的成员函数中使用不完整类型

Evg*_*Evg 7 c++ templates c++17

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;
}
Run Code Online (Sandbox Code Playgroud)

GCC和MSVC接受它,而Clang拒绝它。即使我foo自己做为模板和/或根本不调用它,Clang也会拒绝它。

我的理解是,foo除非调用它,否则不会实例化它,而在调用它时将它实例化。在这一点上C是完整的,和代码应编译。这是海湾合作委员会的理由吗?

附带说明一下,如果foo未调用,即使我C用未声明的C2内部替换,MSVC也会接受代码foo-在这种情况下,它似乎只是检查函数体在语法上是否正确。

根据标准,哪种行为是正确的?如果是Clang,为什么标准禁止GCC提供的灵活性?

Bar*_*rry 12

由于[temp.res] / 8,这是错误的格式,无需诊断:

该程序格式错误,如果满足以下条件,则无需进行诊断:

  • [...]
  • 由于不依赖模板参数或[...]的构造,模板定义后立即进行假想实例化的格式不正确
  • [...]

因此,整个程序很糟糕,但是不需要执行即可对其进行诊断。Clang可以,这对clang很好,而gcc和MSVC却不可以,这没错。