detail 命名空间中的 using 指令有问题吗?

Is a using-directive in a detail namespace problematic?

提问人:Davis Herring 提问时间:9/12/2017 最后编辑:L. F.Davis Herring 更新时间:5/12/2019 访问量:1019

问:

请考虑以下库标头:

#include<vector>
#include<algorithm>
#include<iostream>

namespace Lib {
  namespace detail {
    using namespace std;

    template<class T>
    void sort_impl(istream &in,ostream &out) {
      vector<T> v;
      {
        int n;
        in >> n;
        v.resize(n);
      }
      for(auto &i : v) cin >> i;

      sort(v.begin(),v.end());
      for(auto i : v) out << i << endl;
    }
  }

  inline void sort_std() {
    detail::sort_impl<int>(std::cin,std::cout);
  }
}

在此示例中,命名空间是否成功地将库的客户端(以及库的其余部分实现)与 using 指令隔离开来?我对为什么“使用命名空间 std”被认为是不好的做法?的讨论不感兴趣,尽管有些论点甚至适用于“包含良好”的 using 指令detail

请注意,存在两个关于相同情况的现有问题,但使用 using-declarations

这可以与它们中的任何一个结合使用,但编辑会很严重。

C++ 命名空间 using 指令

评论

0赞 Henri Menke 9/12/2017
您应该进入 .那你就没事了。using namespace std;sort_impl
0赞 Davis Herring 9/12/2017
如果 using 指令位于 中,则必须在其签名中限定 and。(这不是一场灾难,但避免这种冗长是使用指令的原因!您还必须为每个功能配备一个。sort_implistreamostream

答:

3赞 Henri Menke 9/12/2017 #1

,命名空间不会将客户端与嵌套指令隔离开来。[namespace.udir] 对此非常明确detailusing

using 指令指定指定命名空间中的名称可以在 using 指令出现在 using 指令之后的作用域中使用。非限定名称查找期间,名称看起来就像在最近的封闭命名空间中声明一样,该命名空间同时包含 using 指令和指定的命名空间。[注:在此上下文中,“包含”是指“直接或间接包含”。

一个小例子

#include <iostream>

namespace foo {
    namespace detail {
        using namespace std;
    }
}

int main()
{
    foo::detail::cout << "Hello World!\n";

    // nothing is stopping me from doing that
    using namespace foo::detail;
    cout << "Hello World!\n";
}

STL在他的视频Core C++, 1 of n中很好地解释了名称查找是如何工作的。

评论

5赞 StoryTeller - Unslander Monica 9/12/2017
命名空间的全部意义在于将实现细节放在那里。开发人员应该是成年人,而不仅仅是把细节拉进来。在 boost 等库中工作。我想你误解了OP的意图。他们希望防止意外的名称冲突,而不是客户搬起石头砸自己的脚。detail
2赞 Passer By 9/12/2017
我认为 OP 正在询问非滥用案例
0赞 Henri Menke 9/12/2017
@StoryTeller »使界面易于正确使用,而难以错误地使用。(斯科特·迈耶斯)如果你能做到,就会有人去做。因此,通过在命名空间或全局范围内没有声明来保护每个人。using namespace detail;using namespace
3赞 StoryTeller - Unslander Monica 9/12/2017
@HenriMenke - 我同意斯科特的观点。因此,detail 命名空间不是接口的一部分。你有点歪曲他所说的话。负责任的成人方法适用于大量仅 C++ 标头库。我已经命名了 boost,但如果您不相信,您也应该查找标准库标头的作用。
2赞 StoryTeller - Unslander Monica 9/12/2017
另外,并不是你的答案不正确,而是(+1)。在我看来,这太谨慎了。
8赞 StoryTeller - Unslander Monica 9/12/2017 #2

您污染了自己的名称,但不会污染 or 全局命名空间。因此,假设一个负责任的成年人正在使用您的图书馆,他们不会有无意的名称冲突:detailLib

#include <vector>

namespace Lib {
  namespace detail {
    using namespace std;
  }
}

using namespace Lib;

int main() {
    vector<int> v; // This is an error, vector not declared in this scope
}

评论

0赞 Passer By 9/12/2017
这里会推荐一个额外的匿名命名空间吗?
1赞 StoryTeller - Unslander Monica 9/12/2017
@PasserBy - 否如果在标头中声明,那么我认为这可能会导致其中声明的任何类型的 ODR 违规。匿名命名空间在每个翻译单元中都是“不同的”。Lib
2赞 DrSvanHay 9/12/2017
+1 这应该是公认的答案。隔离不是为了防止故意滥用,而只是为了使行为的用户能够避免不必要的副作用。