假设我有一个库,它将所有声明放在命名空间foo
中。然后,我可以通过添加:
using namespace foo;
到我的源文件。但是,如果foo
中的任何无辜名称(例如class foo::socket
)现在与全局命名空间名称(例如::socket()
)不明确。更重要的是,没有办法消除它们的歧义!看起来using namespace
仅对不与全局命名空间冲突的库有用,或者我遗漏了什么?
编辑:通过"消除歧义"我的意思是一次,而不是每个使用网站,这当然是可能的。
我想我们必须等待模块才能获得满意的解决方案。
答案 0 :(得分:7)
回答你的问题 - 它没有用处,它符合你的想法。在某些情况下(就像我在下面描述的那样,它可以是可接受的事情)
确实可能使名称含糊不清,导入整个命名空间时必须非常小心,请参阅Why is "using namespace std" considered bad practice?
我通常只在函数的小范围内导入整个命名空间,例如
void func() {
using namespace foo;
// ...
}
绝对不要在实现文件的顶部执行此操作。直到你完全确定它不会引起任何冲突。
答案 1 :(得分:1)
更重要的是,没有办法消除歧义!
你在那个帐号上错了。始终允许使用完全限定名称:
int main() {
using namespace foo;
foo::socket fs;
::socket s; // no ambiguity
}
你说的是,它确实可能很容易引起歧义。因此,经验法则不是无所畏惧地引入标识符。如果需要,请在所需的最小范围内进行。此外,尽量拉你需要的东西。即:
int main() {
using foo::reader; // not using namespace foo; for a single identifier.
reader r;
socket s; // no ambiguity;
}
当然,如果您需要命名空间中的许多内容,最好将所有内容都放入范围,IMO。
作为旁注,有时将标识符拉入具有相同标识符的范围是一件好事。考虑std::iter_swap
的可能实现:
template<class ForwardIt1, class ForwardIt2>
void iter_swap(ForwardIt1 a, ForwardIt2 b)
{
using std::swap;
swap(*a, *b);
}
你可能想知道在这种情况下为什么要使用using指令,但原因实际上是更好的代码。如果迭代器指向名称空间foo中定义了自定义非成员交换函数的用户定义类,则在找到argument dependent lookup后将调用该函数。
另一方面,如果未找到自定义交换功能,则std::swap
将被称为后备。这是因为using指令使它成为重载决策期间候选函数集的一部分。