Quote
My guess at why would be because "using namespace" simply adds the members of the namespace to the lookup list but gives them lowest precedence when choosing from name conflicts
Not entirely true
namespace A
{
static const char str[] = "A::str";
namespace B
{
static const char str[] = "A::B::str";
}
void foo1()
{
using namespace B;
std::cout << str << std::endl; // error, str is ambiguous
}
namespace C
{
namespace D
{
const char str[] = "A::C::D::str";
}
void foo2()
{
using namespace D;
std::cout << str << std::endl; // uses A::C::D::str
}
}
}
Indeed for a using declaration ("using A::str;"), it introduces the name in the current scope. For using directives ("using namespace A;") however, the name is introduced in the nearest enclosing namespace that contains both the current scope
and the referred namespace.
In the first example, in B::foo1(), B::str has priority over A::str because the nearest enclosing namespace containing both B::foo1 and A is the global namespace, so B::str hides A::str.
In the example above, in A::B::foo1(), the nearest enclosing namespace containing A::B and A::foo1() is A. However, A itself also has a str, so A::str and A::B::str are on the same level within the context of foo1() and 'str' is therefore ambiguous.
In A::C::foo2(), the nearest enclosing scope containing A::C::D and A::C::foo2() is A::C. Therefore A::C::D::str hides the definition of A::str within the context of foo2()