模板函数中使用的类的前向声明不是由 clang++ 编译的
Forward declaration of class used in template function is not compiled by 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(主干)给出了这个错误:
main.cpp:5:6: error: variable has incomplete type 'A'
A a;
^
main.cpp:1:7: note: forward declaration of 'A'
class A;
^
那么根据C++标准,哪个编译器是正确的呢?
那么根据C++标准,哪个编译器是正确的呢?
两者都是正确的。这是一个格式不正确的程序。强调我的:
N3290 14.6¶9
如果非依赖名称中使用的类型在定义模板时不完整,但在完成实例化时完成,并且如果该类型的完整性影响程序的格式是否正确或影响程序的语义,则程序格式不正确;不需要诊断。
clang++ 和其他编译器确实在这里发出诊断是一个不错的附加功能,但诊断不是强制性的。该条款"程序格式不正确;无需诊断",使编译器开发人员可以自由地在这种情况下执行几乎任何事情,并且仍然合规。
我所知,Clang是正确的。在你的函数乐趣中,你不知道 A 的大小,既然你分配了一个 A,你需要知道它的大小。在我看来,gcc 是在这里宽恕的方式。
clang++
使用正确的行为,这在标准(N1905)的第4.6/9
节中有描述。
Templates 14.6/9 Name resolution
如果名称不依赖于模板参数(如 14.6.2),该名称的声明(或一组声明)应在模板中出现该名称时在范围内 定义;名称绑定到声明(或声明) 此时找到,并且此绑定不受声明的影响 在实例化点可见。
用更简单的术语来说;如果名称不依赖于模板参数,它应该在找到定义的范围内;因此你需要在定义template<typename T> void fun ()
之前定义A
。
Comeau的编译器也不喜欢它:
"ComeauTest.c", line 5: error: incomplete type is not allowed
A a;
^
然而,我试图在C++标准中找到章节和经文,但没有结果。它似乎隐藏在"实例化点"、"名称解析"的行间和交互之间。2003年标准第14.6/8段和第14.6/9段似乎具有相关性。
- 是什么原因导致它无法编译?它是声明签名还是在函数本身的实现中
- 未声明的标识符编译暗黑破坏神 2 程序"muleview"
- 模板方法访问正向声明的类仅在没有此指针的情况下无法编译
- 使用直接大括号初始化时,C++ 编译错误"声明末尾的预期";"
- 即使不包含其标头,如何成功向前声明的类编译?
- 如何制作 cmakelists.txt编译使用在其他地方声明和实现的函数和类的 CPP
- C++ 在编译过程中 strtok 函数 Eclipse 说没有在范围内声明?
- Lamda 仅在声明为"自动"时编译,而不是在声明为'bool'时编译
- 由于值返回函数中的错误,程序无法编译.它说未声明的标识符
- C++ SPDLOG 编译错误:变量或字段"set_error_handler"声明为无效
- 在 mingw64- 变量下的窗口中编译 openvpn3 时出错,未在范围内声明
- 尝试编译GoogleTest,但出现以下错误:尚未声明'::OpenThread'
- 如何实现声明功能-C 11,编译时间
- 可变参数模板仅在正向声明时编译
- std::d eclare_if 或其他在编译时丢弃成员声明的假设方法
- 编译错误 在 C++ 上,Calcarea 未在此范围内声明
- 试图过渡到GTK3(针对GTK -3.0库编译)时,在此范围内未声明GTK_Object
- 声明/编译向量中的2d向量
- 需要不完整的类型/正向声明/编译理解
- 使用前向声明编译时"null"?