AFAIK директива using раскрывает или вводит все имена пространства имен в ближайшее окружающее пространство имен. и вот из праймера C++:
In contrast, a using directive makes the entire contents of a namespace available In general, a namespace might include definitions that cannot appear in a local scope. As a consequence, a using directive is treated as if it appeared in the nearest enclosing namespace scope.
In the simplest case, assume we have a namespace A and a function f, both defined at global scope. If f has a using directive for A, then in f it will be as if the names in A appeared in the global scope prior to the definition of f
И из cppreference:
- using-directive: From the point of view of unqualified name lookup of any name after a using-directive and until the end of the scope in which it appears, every name from ns_name is visible as if it were declared in the nearest enclosing namespace which contains both the using-directive and ns_name.
#include <iostream>
int x = 1;
int y = 2;
int z = 3;
namespace A{
namespace B{
int x = 5;
int y = 10;
int z = 0;
}
void foo(){
using namespace A::B;
std::cout << x << '\t' << y << '\t' << z << '\n'; // x, y, z are not ambiguous
}
}
namespace AA{
namespace BB{
void bar(){
using namespace A::B;
std::cout << x << '\t' << y << '\t' << z << '\n'; // x, y, z are ambiguous
}
}
}
int main(){
A::foo(); // works fine
AA::BB::bar(); // fails to compile
std::cout << "\ndone!\n";
}
Почему первая версия работает нормально (функция A::foo()), а вторая - нет (AA::BB::bar())?
Я нахожу немного сбивающим с толку «введение имен в ближайшее пространство имен, которое используется директивой using и определением пространства имен».





Да, это довольно запутанно, но приведенная вами цитата точно объясняет, что происходит. В вашем первом примере (уменьшенное количество переменных до 1):
int x = 1;
namespace A {
namespace B {
int x = 5;
}
void foo(){
using namespace A::B;
std::cout << x << '\n';
}
}
Ближайшее пространство имен будет A. По сути, код был бы эквивалентен
int x = 1;
namespace A {
int x = 5;
void foo(){
std::cout << x << '\n'; // x from NS a.
}
}
x будет именем, определенным в A, и будет использоваться.
Во втором примере
namespace AA {
namespace BB {
void bar() {
using namespace A::B;
std::cout << x << '\n';
}
}
}
ближайшее пространство имен будет глобальным пространством имен. По сути, код был бы эквивалентен
int x = 1;
int x = 5;
namespace AA {
namespace BB {
void bar() {
std::cout << x << '\n';
}
}
}
Этот код будет искажен, поскольку x нельзя переопределить в той же области.