通过 using 指令在 using-declaration 中查找名称

Name lookup in using-declaration via using-directive

提问人:Supremum 提问时间:7/26/2015 最后编辑:DeduplicatorSupremum 更新时间:7/26/2015 访问量:260

问:

根据 c++ 标准,以下程序的格式是否正确或格式错误?

namespace N { int i; }
using namespace N;
using ::i;
int main() {}

我使用不同的编译器得到不同的结果:

根据 c++ 标准,这个程序的格式是正确还是错误?需要对 c++ 标准的引用。

我试图弄清楚我应该为哪个编译器提交错误。

C++ 语言律师 using 指令 名称查找 using-declaration

评论


答:

4赞 Columbo 7/26/2015 #1

海湾合作委员会错了。限定名称查找确实会考虑 ;§3.4.3.2/2 和 /3:N::i

对于命名空间和名称,命名空间限定的查找集定义如下: 设 be the set of all in 的声明和 (7.3.1) 的内联命名空间集。如果不为空,则为 ;否则,S(X, m) 是 X 中的 using 指令及其内联命名空间集中所有命名空间 N i 的 S(Ni, m) 的并集。

给定(其中是用户声明的命名空间)或给定(其中是全局命名空间),[...] 如果只有一个成员,或者如果 引用的上下文是一个 using-declaration (7.3.3),是 所需的 声明集。
XmS(X, m)S'(X, m)mXXS'(X, m)S(X, m)S'(X, m)X::mX::mXS(X, m)S(X, m)m

程序中只有一个由 using 指令指定的命名空间:。因此,它被包含在联合中,并被解析为 .N::iN::i

请注意,GCC 与其查找不一致:在另一个上下文中使用是可以的。::i

namespace N { int i; }
using namespace N;

int main() {
    ::i = 5;
}

这将编译。使用声明作为上下文的唯一区别显示在上面的引文中,并且不影响既定的结论。

评论

0赞 Columbo 7/26/2015
@bogdan 好吧,我看到这个问题真的很晚(就像几分钟前一样),所以我很幸运能得到第一名;-)
5赞 bogdan 7/26/2015 #2

格式良好。

using 指令不会在全局命名空间中引入名称,但在查找期间会使用它。using-declaration 使用限定查找来查找 ;[3.4.3.2 P1, P2] 中指定了存在 using 指令的限定查找(引自 N4527,当前工作草案):ii

如果 qualified-idnested-name-specifier 指定命名空间 (包括 nested-name-specifier 为 的情况,即 nominating the global namespace),在命名空间的作用域中查找 nested-name-specifier 之后指定的名称。[...]::

对于命名空间和名称,命名空间限定的查找集 S(X,m) 定义如下: 设 S'(X,m) 是所有 in 的声明和 (7.3.1) 的内联命名空间集。如果 S'(X,m) 不为空,则 S(X,m) 为 S'(X,m); 否则,S(X,m) 是 所有命名空间 N i 提名的 S(Ni,m 的并集 通过 using 指令及其内联命名空间集。XmmXXX

因此,对于限定的查找,第一步是直接在 nested-name-specifier 指示的命名空间中查找 made 的声明(在本例中)。没有这样的声明,因此 lookup 然后进行第二步,即在全局命名空间中由 using 指令提名的所有命名空间中形成所有 found by qualified lookup 声明的集合。该集由 组成,它是名称查找的结果,并通过 using 声明作为名称引入全局命名空间。i::iN::i

我发现值得注意的是(尽管很明显)限定查找的这个定义是递归的:使用引号中的符号,每个命名空间 N i 中的限定查找将首先查找直接在 N i 中做出的声明,然后,如果找不到,则依次继续查找由 N i 中的 using 指令指定的命名空间, 等等。


就其价值而言,MSVC 也接受代码。

评论

0赞 Supremum 7/26/2015
我现在向 GCC 报告了这个错误:gcc.gnu.org/bugzilla/show_bug.cgi?id=67008