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