提问人:Supremum 提问时间:7/26/2015 最后编辑:DeduplicatorSupremum 更新时间:7/26/2015 访问量:260
通过 using 指令在 using-declaration 中查找名称
Name lookup in using-declaration via using-directive
问:
根据 c++ 标准,以下程序的格式是否正确或格式错误?
namespace N { int i; }
using namespace N;
using ::i;
int main() {}
我使用不同的编译器得到不同的结果:
- Clang (http://melpon.org/wandbox/permlink/c8vl7XbumyyS6vsw):没有错误。
- GCC (http://melpon.org/wandbox/permlink/immhNeWFCMcCA800):错误:“i”未声明。
根据 c++ 标准,这个程序的格式是正确还是错误?需要对 c++ 标准的引用。
我试图弄清楚我应该为哪个编译器提交错误。
答:
海湾合作委员会错了。限定名称查找确实会考虑 ;§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(N
i, m)
的并集。
给定(其中是用户声明的命名空间)或给定(其中是全局命名空间),[...] 如果只有一个成员,或者如果 引用的上下文是一个 using-declaration (7.3.3),是 所需的 声明集。X
m
S(X, m)
S'(X, m)
m
X
X
S'(X, m)
S(X, m)
S'(X, m)
X::m
X
::m
X
S(X, m)
S(X, m)
m
程序中只有一个由 using 指令指定的命名空间:。因此,它被包含在联合中,并被解析为 .N
::i
N::i
请注意,GCC 与其查找不一致:在另一个上下文中使用是可以的。::i
namespace N { int i; }
using namespace N;
int main() {
::i = 5;
}
这将编译。使用声明作为上下文的唯一区别显示在上面的引文中,并且不影响既定的结论。
评论
格式良好。
using 指令不会在全局命名空间中引入名称,但在查找期间会使用它。using-declaration 使用限定查找来查找 ;[3.4.3.2 P1, P2] 中指定了存在 using 指令的限定查找(引自 N4527,当前工作草案):i
i
如果 qualified-id 的 nested-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 指令及其内联命名空间集。
X
m
m
X
X
X
因此,对于限定的查找,第一步是直接在 nested-name-specifier 指示的命名空间中查找 made 的声明(在本例中)。没有这样的声明,因此 lookup 然后进行第二步,即在全局命名空间中由 using 指令提名的所有命名空间中形成所有 found by qualified lookup 声明的集合。该集由 组成,它是名称查找的结果,并通过 using 声明作为名称引入全局命名空间。i
::
i
N::i
我发现值得注意的是(尽管很明显)限定查找的这个定义是递归的:使用引号中的符号,每个命名空间 N i 中的限定查找将首先查找直接在 N i 中做出的声明,然后,如果找不到,则依次继续查找由 N i 中的 using 指令指定的命名空间, 等等。
就其价值而言,MSVC 也接受代码。
评论