通过 using-directive 在 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++ 标准。
我想弄清楚我应该为哪个编译器提交错误。
GCC 错误。限定名称查找确实考虑 N::i
; §3.4.3.2/2 & /3:
For a namespace X
and name m
, the namespace-qualified lookup set
S(X, m)
is defined as follows: Let S'(X, m)
be the set of all
declarations of m
in X
and the inline namespace set of X
(7.3.1). If S'(X, m)
is not empty, S(X, m)
is S'(X, m)
;
otherwise, S(X, m)
is the union of S(N
i, m)
for all namespaces N
i nominated by using-directives in X
and its inline namespace set.
Given X::m
(where X
is a user-declared namespace), or given ::m
(where
X
is the global namespace), […] if S(X, m)
has exactly one member, or if the
context of the reference is a using-declaration (7.3.3), S(X, m)
is
the required set of declarations of m
.
您的程序中只有一个由 using 指令指定的名称空间:N
。因此它包含在联合中并且 ::i
被解析为 N::i
.
请注意,GCC 与其查找不一致:在另一个上下文中使用 ::i
没问题。
namespace N { int i; }
using namespace N;
int main() {
::i = 5;
}
这个compiles。 using 声明作为上下文的唯一区别显示在上面的引用中,并且不会影响既定的结论。
格式正确。
using-directive 没有在全局命名空间中引入名称 i
,但在查找期间使用它。 using-declaration 使用限定查找来查找 i
; using-directives 存在的合格查找在 [3.4.3.2 p1, p2] 中指定(引自 N4527,当前工作草案):
If the nested-name-specifier of a qualified-id nominates a namespace
(including the case where the nested-name-specifier is ::
, i.e.,
nominating the global namespace), the name specified after the
nested-name-specifier is looked up in the scope of the namespace. [...]
For a namespace X
and name m
, the namespace-qualified lookup set
S(X,m) is defined as follows: Let S'(X,m) be the set of all
declarations of m
in X
and the inline namespace set of X
(7.3.1). If
S'(X,m) is not empty, S(X,m) is S'(X,m); otherwise, S(X,m) is the
union of S(Ni,m) for all namespaces Ni nominated
by using-directives in X
and its inline namespace set.
因此,对于合格的查找,第一步是查找直接在 nested-name-specifier (::
在这种情况下)。没有这样的声明,所以 lookup 然后进行到第二步,即在 using-directives[=47] 指定的所有名称空间中通过合格查找找到的 i
的所有声明形成集合=] 在全局命名空间中。该集合由 N::i
组成,这是名称查找的结果,并通过 using 声明作为名称引入全局命名空间。
我发现值得注意(虽然很明显)限定查找的定义是递归的:使用引号中的符号,每个命名空间中的限定查找 Ni 将首先查找直接在 Ni 中进行的声明,然后,如果找到 none,将依次查看 using-directives 在 Ni 中指定的命名空间,等等上。
就其价值而言,MSVC 也接受该代码。
根据 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++ 标准。
我想弄清楚我应该为哪个编译器提交错误。
GCC 错误。限定名称查找确实考虑 N::i
; §3.4.3.2/2 & /3:
For a namespace
X
and namem
, the namespace-qualified lookup setS(X, m)
is defined as follows: LetS'(X, m)
be the set of all declarations ofm
inX
and the inline namespace set ofX
(7.3.1). IfS'(X, m)
is not empty,S(X, m)
isS'(X, m)
; otherwise,S(X, m)
is the union ofS(N
i, m)
for all namespacesN
i nominated by using-directives inX
and its inline namespace set.
GivenX::m
(whereX
is a user-declared namespace), or given::m
(whereX
is the global namespace), […] ifS(X, m)
has exactly one member, or if the context of the reference is a using-declaration (7.3.3),S(X, m)
is the required set of declarations ofm
.
您的程序中只有一个由 using 指令指定的名称空间:N
。因此它包含在联合中并且 ::i
被解析为 N::i
.
请注意,GCC 与其查找不一致:在另一个上下文中使用 ::i
没问题。
namespace N { int i; }
using namespace N;
int main() {
::i = 5;
}
这个compiles。 using 声明作为上下文的唯一区别显示在上面的引用中,并且不会影响既定的结论。
格式正确。
using-directive 没有在全局命名空间中引入名称 i
,但在查找期间使用它。 using-declaration 使用限定查找来查找 i
; using-directives 存在的合格查找在 [3.4.3.2 p1, p2] 中指定(引自 N4527,当前工作草案):
If the nested-name-specifier of a qualified-id nominates a namespace (including the case where the nested-name-specifier is
::
, i.e., nominating the global namespace), the name specified after the nested-name-specifier is looked up in the scope of the namespace. [...]For a namespace
X
and namem
, the namespace-qualified lookup set S(X,m) is defined as follows: Let S'(X,m) be the set of all declarations ofm
inX
and the inline namespace set ofX
(7.3.1). If S'(X,m) is not empty, S(X,m) is S'(X,m); otherwise, S(X,m) is the union of S(Ni,m) for all namespaces Ni nominated by using-directives inX
and its inline namespace set.
因此,对于合格的查找,第一步是查找直接在 nested-name-specifier (::
在这种情况下)。没有这样的声明,所以 lookup 然后进行到第二步,即在 using-directives[=47] 指定的所有名称空间中通过合格查找找到的 i
的所有声明形成集合=] 在全局命名空间中。该集合由 N::i
组成,这是名称查找的结果,并通过 using 声明作为名称引入全局命名空间。
我发现值得注意(虽然很明显)限定查找的定义是递归的:使用引号中的符号,每个命名空间中的限定查找 Ni 将首先查找直接在 Ni 中进行的声明,然后,如果找到 none,将依次查看 using-directives 在 Ni 中指定的命名空间,等等上。
就其价值而言,MSVC 也接受该代码。