“using namespace std::placeholders;”符合标准吗?

5
从§ 2.10.3.2节中可以得知:
以下划线开头的每个标识符都被保留给实现用作全局命名空间中的名称。
考虑到这一点,这个程序是否符合标准呢?因为它使得_1等在全局命名空间中可用。或者说它是可以的,因为std::placeholders被认为是"实现"?还是因为_1实际上并不存在于全局命名空间中?还是其他什么原因呢?
using namespace std::placeholders;
int main(){}

1
就我所理解的,它被保留意味着全局命名空间中的任何“_1”都必须来自于“实现”,而标准库是“实现”的一部分。 - molbdnilo
1个回答

7
我认为这个程序很好。严格来说,using-directive 并不会将任何名称放入命名空间中——它使得这些名称可以通过名称查找访问,但并不实际将它们作为包含 using-directive 的命名空间的成员。
引用 C++11, 7.3.4:
2.using-directive 指定了指定命名空间中的名称可以在 using-directive 出现后的作用域中使用。在未限定名称查找(3.4.1)期间,这些名称出现在最近的封闭命名空间中,该封闭命名空间包含使用 using-directive 和指定的命名空间。[注意:在此上下文中,“包含”意味着“直接或间接包含”。—end note]
3.using-directive 不会向其出现的声明区域添加任何成员。...
请注意“可以使用”的语言,“好像它们被声明为”等语言。没有提到实际将名称作为不同命名空间的成员。
至于通过限定名称进行访问,3.4.3.2(命名空间的限定名称查找)如下所述:
2.对于命名空间 X 和名称 m,命名空间限定查找集 S(X,m) 定义如下:令 S'(X,m) 为 X 中 m 的所有声明和 X 的内联命名空间集合(7.3.1)中的所有声明的集合。如果 S'(X,m) 不为空,则 S(X,m) 为 S'(X,m);否则,S(X,m) 是 X 的 using-directives 中提名的所有命名空间 Ni 和其内联命名空间集的 S(Ni,m) 的并集。
即,对于 using-directive 有单独的规则。
我从中得出结论:using-directive 不会使任何名称成为命名空间的成员,因此不会触发 _ 全局命名空间规则,也不会导致未定义行为。

这基本上就是我最初的回答,只不过我发布了一个我预计会失败但实际上没有失败的程序。你引用的解释说明了未经限定的名称查找将成功,但是经过限定的名称查找也能成功。关于这方面还有更多的细节,不在你的答案中涵盖。我也在试图找到标准中相关的其他部分。 - user743382
但是,如果我是一名编译器编写者,并且出于某种原因在我的实现中使用 _1 并将其放置在全局命名空间中,是否会被 using namespace std; 遮蔽?如果是这样,那么这会破坏我的实现吗? - OmnipotentEntity
1
作为一名负责任的编译器编写者,如果有任何可能引起混淆的情况,您应该始终完全限定所有内容。这意味着当您指的是特定于实现的“_1”符号时,您应始终编写“::_1”。根据3.4.3.2/2,找到限定命名空间的实际成员会禁用使用指令查找。所以您不会有问题。 - Angew is no longer proud of SO
谢谢!那正是我需要知道的。 - OmnipotentEntity
这正是我在示例程序中犯错的地方。namespace N { void f() { } } using namespace N; int main() { ::f(); } 是有效的并且明确调用了 N::fnamespace N { void f() { } } using namespace N; void f() { } int main() { ::f(); } 也是有效的,尽管对 f() 的调用现在会产生歧义,但对 ::f 的调用仍然是明确的。 - user743382
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接