提问人:Davis Herring 提问时间:9/12/2017 最后编辑:L. F.Davis Herring 更新时间:5/12/2019 访问量:1019
detail 命名空间中的 using 指令有问题吗?
Is a using-directive in a detail namespace problematic?
问:
请考虑以下库标头:
#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++ 中防止命名空间中毒的优雅方法(其一个答案实际上是对上面“不良实践”问题的回答)
这可以与它们中的任何一个结合使用,但编辑会很严重。
答:
3赞
Henri Menke
9/12/2017
#1
否,命名空间不会将客户端与嵌套指令隔离开来。[namespace.udir] 对此非常明确detail
using
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 全局命名空间。因此,假设一个负责任的成年人正在使用您的图书馆,他们不会有无意的名称冲突:detail
Lib
#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 这应该是公认的答案。隔离不是为了防止故意滥用,而只是为了使行为的用户能够避免不必要的副作用。
评论
using namespace std;
sort_impl
sort_impl
istream
ostream