模板函数中使用的类的前向声明不是由clang ++编译的

时间:2012-06-12 09:19:37

标签: c++ templates g++ forward-declaration clang++

有这段代码:

class A;

template <class T>
void fun() {
   A a;
}

class A { 
public: 
   A() {  } 
};

int main() { 
   fun<int>(); 
   return 0;
}

g ++ 4.5和g ++ 4.7编译时没有错误。但是clang ++ 3.2(trunk)给出了这个错误:

main.cpp:5:6: error: variable has incomplete type 'A'
   A a;
     ^
main.cpp:1:7: note: forward declaration of 'A'
class A;
      ^

根据C ++标准,哪个编译器正确?

4 个答案:

答案 0 :(得分:12)

  

根据C ++标准,哪个编译器正确?

两者都是正确的。这是一个不正常的计划。强调我的:

  

N329014.6¶9
  如果非依赖名称中使用的类型在定义模板但在完成实例化时完成,并且该类型的完整性影响程序是否良好时,则不完整形成或影响程序的语义,程序形成不良;无需诊断

clang ++和其他编译器确实在这里发出诊断是一个很好的补充功能,但诊断并不是强制性的。该条款“该程序格式不正确;不需要诊断”使编译器开发人员可以在这种情况下自由执行任何操作,并且仍然符合要求。

答案 1 :(得分:5)

据我所知,Clang是正确的。在你的功能乐趣,你不知道A的大小,并且因为你分配A,你需要知道它的大小。在我看来,gcc是在这里原谅的方式。

答案 2 :(得分:1)

clang++正在使用正确的行为,标准部分4.6/9 n1905 )中对此进行了描述。


  

<强> Templates 14.6/9 Name resolution

     

如果名称不依赖于模板参数(如中所定义)    14.6.2 ),该名称的声明(或一组声明)应在名称出现在模板中的范围内   定义;名称与声明(或声明)绑定   在那一点上找到并且此绑定不受声明的影响   在实例化时可见。


简单易懂;如果名称依赖于模板参数,则它应该在找到定义的范围内;因此,您需要在定义A之前定义template<typename T> void fun ()

答案 3 :(得分:0)

Comeau的编译器也不喜欢它:

"ComeauTest.c", line 5: error: incomplete type is not allowed
     A a;
       ^

然而,我在C ++标准中寻找章节和诗句的尝试毫无结果。它似乎隐藏在“实例化点”,“名称解析”的界限和交互之间。 2003年标准的第14.6 / 8和14.6 / 9段似乎是相关的。