【问题标题】:why are parts of the standard library in a separate namespace为什么标准库的一部分在单独的命名空间中
【发布时间】:2018-01-18 15:04:38
【问题描述】:

为什么 C++ 标准库的某些部分(在最近的标准中似乎越来越普遍)不直接位于 ::std 命名空间中,而是位于嵌套命名空间中? std::chronostd::filesystem 是我脑海中浮现的两个例子。

【问题讨论】:

  • 已经对标准命名空间的元素进行了分类,即std::chrono::duration 当然特定于计时。这也不是什么新鲜事。以std::string::npos 为例。
  • @JustinRandall:std::string::npos 不是命名空间。你的例子没有回答这个问题。向量是特定于容器的,那为什么没有std::container 命名空间呢?
  • 致那些以意见为基础投票结束的人:让我指出,我并没有要求讨论将事物放在嵌套命名空间中的利弊,我问为什么这样做是在这些案件,对于任何参与或听取做出此决定的人来说,这应该是一个基于事实的问题。如果其他人提出他们有根据的猜测(我完全赞成),这不会使问题基于意见
  • 这个问题可以用事实来回答;它不应该仅仅因为迄今为止的大多数答案主要是基于意见而关闭。投票重新开放。
  • 回复:std::chronostackoverflow.com/a/13442036/576911

标签: c++


【解决方案1】:

显而易见的原因与任何其他项目相同:如果没有它,就会出现名称冲突。例如,std::filesystem::copystd::copy

这不是一个完整的解释,因为

  • 我无法立即看到 std::chrono 命名空间中的任何冲突
  • 委员会本可以选择一个不冲突的名称来代替

更有说服力,

  1. 这些库基于它们的 Boost 前身,因为这些库已被证明是有用的并且经过了良好的测试。这意味着存在使用它们的现有代码,如果命名空间结构没有改变,并且没有引入新的冲突,则更容易将该代码移植到 C++11 版本。
  2. 更广泛地说,自标准库的第一个版本以来,C++ 最佳实践不断发展。

请注意(正如 Default 在评论中指出的那样),正则表达式库选择与 Boost over namespace 最佳实践的一致性,因此看起来 #1 更重要。 std::thread 等也是如此。


将事实与推测和假设分开:

  • 讨论的库基于 Boost 前辈
  • 讨论的库保留了其 Boost 前辈的命名空间结构
  • 所讨论的库的命名空间结构彼此不一致(或与标准库的其余部分)
  • 在 C++ 中更改命名空间结构,即使没有名称冲突,也会产生与 ADL 相关的副作用(因此它不是简单的搜索和替换)

结论:选择命名空间结构是为了与 Boost 保持一致,而不是与标准库的其余部分保持一致,甚至与 C++11 中添加的库保持一致。

【讨论】:

  • 没有想到与 Boost 的连接,从实际的角度来看这是有道理的,但老实说,我不确定它是否证明缺乏一致性......如果你可以运行 sed -e 's/boost::/std::/g'你可以运行sed -e 's/boost::regex_/std::regex::/g'...
  • @jdehesa:更改命名空间结构可能会引入错误(使用 ADL)。
  • 您在这里遗漏了重要的一点,用户代码chrono 包含常用名称,例如 durationhours。将它们直接放在 std 中可能会导致名称冲突或与执行 using namespace std; 的 C++-11 之前的代码产生歧义。 (我不打算在这里讨论做或不做using namespace std; 的相对优点……这只是可能的委员会推理。)
  • @ArneVogel:如果你有 using namespace std;struct thread; 的 pre-C++11 代码?
  • 我接受这个答案,因为没有发布任何带有实际事实的答案(“我是委员会成员,这就是我们这样做的原因......”),这是唯一一个看起来成为有利于它的很好的证据。
【解决方案2】:

拥有多个命名空间可以最大限度地减少出现别名问题的机会。标准库中的所有内容都必须在std:: 内,好的,但是标准库对于单个命名空间来说仍然很大。例如,在std::filesystem 中,您有函数std::filesystem::status。很容易想象库的其他部分在某些时候可能需要status 函数。并且命名空间在阅读代码时也让函数的用途或“领域”更加清晰。

此外,例如,如果您在代码中的某个位置是 using namespace std;,则您自己可能在当前命名空间中有一些 status 函数,这样您就可以避免重复 std:: 而无需拉动每一件事从标准库直接导入本地命名空间,或者更有选择性地选择您想要引入的特定名称子集。

也就是说,将 API 分解为无数的命名空间也不太实用。也许更熟悉 C++ 标准化过程的人可以给出更完整的答案,详细说明委员会如何决定何时添加命名空间,但归根结底是设计和风格的问题,没有明确的、不容置疑的规则。

【讨论】:

  • 或者可以写成filesystem_status,就像他们写regex_match一样。
  • @Default 是的,这就是我添加最后一段的原因......老实说,我认为这可能是一个命名空间,例如 std::sub_match 甚至没有 regex 的名称和我不认为它与正则表达式有关。但话又说回来,我知道什么,我想这是委员会内部扩大讨论的结果......
【解决方案3】:

考虑std::filesystem::absolute

没有filesystem 子命名空间,这个函数应该被命名为std::filesystem_absolute。这是一种可行的方法,但不如使用子命名空间的方法灵活。请记住,您可以使用Namespace aliases

似乎在最近的标准中它变得越来越普遍

我认为是这样,因为标准库变得越来越大。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-08
    • 1970-01-01
    • 1970-01-01
    • 2017-06-01
    • 2023-03-31
    • 2011-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多