以 :: 开头的 C++ 嵌套命名空间定义

4
在草案§7.3.1¶1 (n4527)中,命名空间定义的语法包含以下内容:

enclosing-namespace-specifier:

identifier

enclosing-namespace-specifier :: identifier

这阻止了命名空间定义具有以“::”开头的标识符。
namespace d{ namespace e {} }
namespace ::d::e
{
void foo(){}
}

那个限制有什么原因吗?


更新: 投票和一些回答让我意识到我在第一句话中写错了“标准”,实际上是“草案”。为此,我在括号中写出了文件编号。因此,我强调这是关于C++1z嵌套命名空间定义功能的问题。


给那位点了踩的人。我发布了一段无法编译的代码。我查阅了标准并找到了禁止它的规则。我想了解这个规则背后的原因。为什么要点踩? - Hector
5
这只是一个猜测而不是答案,但很可能是因为前导的::表示全局命名空间。所以命名空间foo {namespace ::bar{}}要么必须停止将::视为全局,要么将bar提升到foo之外,这会很奇怪... 更好的方法是禁止这种写法。 - IdeaHat
你尝试过在namespace关键字之前使用using关键字吗?也许它可以解决问题。 - Ahmet
1
@galinette,不是命名空间标识符以'::'开头。而是封闭的命名空间说明符以'::'开头。毕竟,嵌套名称说明符可以以'::'开头。 - Hector
1
@galinette 但反斜杠在路径中并不被禁止。 - Hector
显示剩余2条评论
2个回答

1
下面的A::的两种用法非常不同:
void f();
namespace A {
  void f();
  namespace B {
    void f();
    void g() {
      A::f();      // #1
      ::f();
    }
  }
}
namespace A::N {}  // #2
namespace /*::*/N {}
  1. 这个选择了一个命名空间,以避免未经限定查找找到B::f。这种用例也适用于全局命名空间,因此需要使用::f;
  2. 这个建立(即创建或重新打开)一个命名空间。这种用例显然不适用于全局命名空间,因此没有理由在最后一行允许::N

0

::开头的行表示您希望使用全局命名空间。例如:

void foo()
{
  std::cout << "1" << std::endl;
}

namespace d
{
  void foo()
  {
    std::cout << "2" << std::endl;
  }

  void example()
  {
    foo();
    ::foo();
  }
}

这段代码将打印出:

2
1

由于第一个调用进入 d::foo(),而第二个调用进入全局命名空间中的 foo()。因此,在命名空间的开头放置一个 :: 会让人误以为你将 d 放在全局命名空间中,而实际上你是想为它创建一个命名空间,这并没有任何意义。


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