What's more, there is no way to disambiguate them!
You are very wrong on that account. Using the fully qualified name is always allowed:
int main() {
using namespace foo;
foo::socket fs;
::socket s; // no ambiguity
}
What you are correct about is that it does indeed may cause ambiguity very easily. So the rule of thumb is not to pull in identifiers willy-nilly. And if you need to, do it at the smallest scope required. Moreover, try to pull just the things you need. i.e:
int main() {
using foo::reader; // not using namespace foo; for a single identifier.
reader r;
socket s; // no ambiguity;
}
Of course, if you need many things from the namespace, it's better to pull everything into scope, IMO.
As a side note, sometimes pulling an identifier into scope with an identical one is a good thing. Consider a possible implementation for std::iter_swap
:
template<class ForwardIt1, class ForwardIt2>
void iter_swap(ForwardIt1 a, ForwardIt2 b)
{
using std::swap;
swap(*a, *b);
}
You may be wondering why bother with a using directive in this case, but the reason is actually better code. If the iterators point at a user defined class in namespace foo that defines a custom non-member swap function, then that function will be called after being found with argument dependent lookup.
If, on the other hand, no custom swap function is found, then std::swap
will be called as a fallback. That's because the using directive makes it be a part of the candidate function set during overload resolution.