是`使用命名空间foo;`没用?

时间:2017-05-21 04:56:41

标签: c++

假设我有一个库,它将所有声明放在命名空间foo中。然后,我可以通过添加:

来方便地使用该库
using namespace foo;

到我的源文件。但是,如果foo中的任何无辜名称(例如class foo::socket)现在与全局命名空间名称(例如::socket())不明确。更重要的是,没有办法消除它们的歧义!看起来using namespace仅对不与全局命名空间冲突的库有用,或者我遗漏了什么?

编辑:通过"消除歧义"我的意思是一次,而不是每个使用网站,这当然是可能的。

我想我们必须等待模块才能获得满意的解决方案。

2 个答案:

答案 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指令使它成为重载决策期间候选函数集的一部分。