Is `using namespace foo;` useless?
Suppose I have a library that places all its declarations in namespace foo
. I can then conveniently use the library by adding:
using namespace foo;
to my source files. However, if any innocent name in foo
(for example class foo::socket
) is now ambiguous with global namespace names (for example ::socket()
). What's more, there is no way to disambiguate them! Looks like using namespace
is only useful for libraries that don't conflict with the global namespace, or am I missing something?
EDIT: by "disambiguate" I meant once for the scope, not at every use site, which is of course possible.
I guess we'll have to wait for modules for a satisfactory solution.
To answer your question - It is not useless, it does what you think. And in some cases (like the one I have described below, it can be an acceptable thing to do)
It can indeed make names ambiguous, you have to be very careful when importing an entire namespace, see Why is "using namespace std" considered bad practice?
I usually only import an entire namespace in the scope of something small like a function, for example
void func() {
using namespace foo;
// ...
}
Definitely never do it at the top of an implementation file. Not until you are absolutely sure that it will not cause any conflicts.
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. ie:
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.
上一篇: “使用命名空间标准”有什么用处?