提问人:Supremum 提问时间:7/19/2015 最后编辑:Supremum 更新时间:7/19/2015 访问量:485
在最接近的封闭范围内使用 using 指令的局部外部变量声明
Local extern variable declaration with using-directive in the nearest enclosing scope
问:
根据 c++ 标准,这个程序的格式是否正确?
namespace X { int i = 1; }
using namespace X;
int main() {
extern int i;
i = 2;
}
我使用不同的编译器得到不同的结果:
GCC 和 Clang 给出链接器错误:对 i 的未定义引用。
Visual c++ 接受该程序。
答:
4赞
David G
7/19/2015
#1
[basic.link]/第6页:
如果存在具有相同名称和类型的链接的实体的可见声明,而忽略在最内层封闭命名空间范围之外声明的实体,则块范围声明将声明该实体并接收前一个声明的链接。如果存在多个此类匹配实体,则程序的格式不正确。否则,如果未找到匹配的实体,则块作用域实体将接收外部链接。
X::i
在 extern 声明的最内层封闭命名空间(即全局命名空间)之外声明,因此它被忽略。这意味着没有找到任何声明,因此是以外部链接命名的新变量的声明。i
extern int i
i
您的程序将编译,但如果使用了 odr-scope,则不会链接。i
评论
0赞
Supremum
7/19/2015
[namespace.udir]p2 ( eel.is/c++draft/namespace.udir#2 ) 在这里不适用吗?
1赞
David G
7/19/2015
@Supremum这也是我关心的问题,但我认为从 [basic.scope.pdecl]/p11 的这个注释中,“块作用域的函数声明和块作用域中带有说明符的变量声明是指作为封闭命名空间成员的声明”,看起来好像它是在全局命名空间中声明的,但它不是成员, 这使得它被排除在查找之外。不过,我在这方面有点不稳定,所以也许知识渊博的人会提出一些明确的东西。extern
X::i
0赞
Supremum
7/19/2015
嗯。。。是的,X::i 显然不是全局命名空间的成员,因为它没有在那里声明,但根据 [namespace.udir]p2 name-lookup 应该表现得像在那里声明的那样,因此是全局命名空间的成员。但是,我认为应用 [basic.link]/p6 不是名称查找。因此,我认为您是对的,我们应该在这里获得链接器错误。这是否意味着 Visual C++ 存在未报告链接器错误的 bug?
1赞
David G
7/19/2015
@Supremum 是的,我认为 VC++ 在这里有一个错误。
0赞
Colin Hicks
1/28/2021
@0x499602D2我本来以为改成会编译。它也失败了,即使这个答案似乎表明使用声明相当于该实体在同一区域的声明。我不明白为什么它仍然失败,因为他们的声明显然是可见的。using namespace X;
using X::i;
评论