这与其说是一个答案,不如说是与其他一些一直主张将命名空间明确包含在名称中的答案的对立面。有时,这是一个糟糕的主意。在某些情况下,您希望使用专门针对手头类型(如果存在)的名称,否则使用标准提供的替代名称。
作为一个典型的例子,让我们考虑一个排序函数。如果你对一些 T 类型的对象进行排序,你最终会交换项目。swap(T &, T&)
如果它存在,你想使用一个特殊的,template <class T> std::swap
否则。
如果您尝试指定要显式使用的交换的全名,则必须指定一个或另一个 - 您指定一个专用版本,并在未定义它自己的类型上实例化您的排序swap 将失败,否则您指定std::swap
,并忽略专门为您要排序的类型提供的任何交换。
using
虽然提供了摆脱这种困境的方法:
using namespace std;
template <class T>
mysort(/* ... */ ) {
// ...
if (less(x[a], x[b])
swap(x[a], x[b]);
// ...
}
现在,如果找到 T 的命名空间包含 a swap(T &, T&)
,它将通过参数相关查找找到,并在上面使用。如果它不存在,那么std::swap
将被找到(并使用),因为using namespace std;
它也使其可见。
顺便说一句,我认为只需稍作修改,using namespace x;
就可以使其几乎完全无害。就目前而言,它将来自该命名空间的名称引入当前范围。如果其中一个恰好与当前作用域中存在的名称相同,则会发生冲突。当然,问题是我们可能不知道命名空间包含的所有内容,因此几乎总是至少有一些潜在的冲突。
修改将被using namespace x;
视为好像它创建了一个围绕当前范围的范围,并将该名称空间中的名称引入该周围范围。如果其中一个恰好与当前作用域中引入的名称相同,则不会发生冲突——就像任何其他块作用域一样,当前作用域中的名称将从周围作用域中隐藏相同的名称。
我没有详细考虑过这一点,所以毫无疑问会有一些极端情况需要更加小心地解决,但我认为总体思路可能会让很多事情变得更简单。