Sup*_*mum 19 c++ declaration using-declaration language-lawyer
根据c ++标准,以下程序是否格式良好或格式不正确?
namespace X { int i; }
namespace Y { using X::i; }
int main() { using X::i; using Y::i; }
Run Code Online (Sandbox Code Playgroud)
我用不同的编译器得到了不同的结果:
我不想修复这个程序让它在GCC上编译.我只是想知道c ++标准对此有何看法以及为什么三个编译器的行为不同.此外,我想如果这是任何这些编译器中的错误的结果.
Che*_*Alf 12
程序不应该编译,因为它X::i在同一块范围内声明了两次.
" using声明是一个声明,因此可以在允许多个声明的地方(并且只在哪里)重复使用.[ 例如:
Run Code Online (Sandbox Code Playgroud)namespace A { int i; } namespace A1 { using A::i; using A::i; // OK: double declaration } void f() { using A::i; using A::i; // error: double declaration }
编辑:上面引用的非规范性评论,我认为它回答了这个问题,最初是在C++ 98中,并且通过技术勘误1(C++ 03),C++ 11和C++ 14得以存活.但显然这是错的.理查德·史密斯在他的回答引用核心问题36这件事,由安德鲁·科尼格2首募次 1998年8月(后不到一个月的第一个标准的ANSI批准),这显然意味着一个已知的不正确的评论可以生存的三次修改标准.
引用核心问题本身:
C++标准核心语言活动问题,第36期:" 04/00会议的说明:
核心语言工作组无法就使用声明应该模仿的声明达成共识.在民意测验,7名委员赞成允许使用-声明任何地方的非定义声明可能出现,而4优选以允许多个使用-eclarations仅在命名空间范围(其理由是用于多个许可使用-声明主要是支持它在多个头文件中的使用,这些头文件很少包含在命名空间范围之外的任何地方.John Spicer指出friend声明可以在类范围内出现多次,并询问using声明是否在"like a declaration"解析下具有相同的属性.由于缺乏协议,该问题又回到了"开放"状态.
关于同名多个声明的一般讨论在C++ 98和C++ 14的§3.3.1/ 4中.据我所知,C++ 14文本与原始的C++ 98文本完全相同.并且它本身允许在许多情况下在同一声明区域中多次声明相同的名称,其中一个是所有声明都引用同一个实体:
C++14§3.3.1/ 4:"给定一个声明区域中的一组声明,每个声明都指定相同的非限定名称,
它们都应指同一实体,或全部指功能和功能模板; 要么
正好一个声明应声明一个不是typedef名称的类名或枚举名,其他声明都应引用相同的变量或枚举,或者全部引用函数和函数模板; 在这种情况下,隐藏类名或枚举名(3.3.10).[ 注意:名称空间名称或类模板名称在其声明性区域中必须是唯一的(7.3.2,第14条).- 尾注 ]
但是,这里的措辞只说明没有直接无效的内容.其他规则可以禁止声明,即使这个规则不允许也不允许.例如,类成员声明有这样的限制:
C++14§9.2/ 1:" [...]成员不应在成员规范中声明两次,除非可以声明嵌套类或成员类模板,然后再定义,除了可以使用opaque-enum-declaration引入枚举,后来用enum-specifier重新声明.
我没有找到这样的限制来支持上面开头引用的C++14§7.3.3/ 10中明显不正确的注释,即我没有找到块范围或命名空间范围的任何特殊处理,因此暂时得出结论(考虑到评论的存在,尽管1998年已经存在争议)是有争议的评论实际上是错误的,并且这个问题的代码,其中同一声明区域中的两个声明指的是同一个实体,是有效的并且应该被接受由所有编译器.
Clang和MSVC是正确的; 此代码有效.正如Alf所说,[namespace.udecl](7.3.3)/ 10说
甲using声明是声明的,因此可以反复使用,其中(并且仅在哪里)多个声明是允许的.
但是,在块作用域中对同一实体的多个声明没有限制,因此原始示例是有效的.不涉及使用声明的相应案例是:
int n;
void f() {
extern int n;
extern int n;
}
Run Code Online (Sandbox Code Playgroud)
这是有效的(并且被GCC,EDG,Clang和MSVC接受),因此(通过上述规则)原始示例也是有效的.
值得注意的是,[namespace.udecl](7.3.3)/ 10中的示例包含错误.它说:
namespace A {
int i;
}
void f() {
using A::i;
using A::i; // error: double declaration
}
Run Code Online (Sandbox Code Playgroud)
......但评论不正确; 第二个声明没有错误.请参阅核心问题36中的讨论.我从标准中删除了这个例子,这样就不会让更多的人感到困惑.
| 归档时间: |
|
| 查看次数: |
376 次 |
| 最近记录: |