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

时间:2019-05-07 14:47:20

标签: 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;
}

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

我的理解是,foo除非被调用,否则不会被实例化,而是在被调用时被实例化。到此,C完成,并且代码应编译。这是海湾合作委员会的理由吗?

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

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

1 个答案:

答案 0 :(得分:12)

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

  

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

     
      
  • [...]
  •   
  • 由于模板不依赖于模板参数或[...]
  • ,因此,紧随其定义的模板的假设实例化将不正确。   
  • [...]
  •   

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