Я считаю, что обоснование состоит в том, что это, вероятно, сбивает с толку.В настоящее время при обработке идентификатора уровня класса поиск сначала выполняет поиск в области класса, а затем во вложенном пространстве имен.Разрешение using namespace
на уровне класса будет иметь некоторые побочные эффекты от того, как теперь выполняется поиск.В частности, это должно быть выполнено где-то между проверкой конкретной области класса и проверкой пространства имен.То есть: 1) объединить поиск уровня класса и используемых уровней пространства имен, 2) поиск используемого пространства имен после области видимости класса, но перед любой другой областью класса, 3) поиск используемого пространства имен непосредственно перед включающим пространством имен.4) поиск объединен с вмещающим пространством имен.
- Это имело бы большое значение, когда идентификатор на уровне класса shadow любой идентификатор в вмещающем пространстве имен, но это не будет тень a используется пространство имен.Эффект был бы странным, так как доступ к используемому пространству имен из класса в другом пространстве имен и из того же пространства имен будет отличаться:
.
namespace A {
void foo() {}
struct B {
struct foo {};
void f() {
foo(); // value initialize a A::B::foo object (current behavior)
}
};
}
struct C {
using namespace A;
struct foo {};
void f() {
foo(); // call A::foo
}
};
- Поиск сразу после этой области видимости.Это имело бы странный эффект слежки за членами базовых классов.Текущий поиск не смешивает поиск на уровне класса и пространства имен, и при выполнении поиска по классу он пойдет до базовых классов до с учетом окружающего пространства имен.Поведение будет удивительным в том смысле, что оно не будет рассматривать пространство имен на уровне, аналогичном вмещающему пространству имен.Снова, используемое пространство имен будет иметь приоритет над вмещающим пространством имен.
.
namespace A {
void foo() {}
}
void bar() {}
struct base {
void foo();
void bar();
};
struct test : base {
using namespace A;
void f() {
foo(); // A::foo()
bar(); // base::bar()
}
};
- Поиск прямо перед вмещающим пространством имен.Проблема с этим подходом состоит в том, что это было бы удивительно для многих.Учтите, что пространство имен определено в другой единице перевода, поэтому следующий код не может быть виден сразу:
.
namespace A {
void foo( int ) { std::cout << "int"; }
}
void foo( double ) { std::cout << "double"; }
struct test {
using namespace A;
void f() {
foo( 5.0 ); // would print "int" if A is checked *before* the
// enclosing namespace
}
};
- Объединить с включеннымПространство имен.Это будет иметь тот же эффект, что и применение объявления
using
на уровне пространства имен.Это не добавит к этому никакого нового значения, но, с другой стороны, усложнит поиск разработчиков компиляторов.Поиск идентификатора пространства имен теперь не зависит от того, где в коде выполняется поиск.Когда внутри класса поиск не находит идентификатор в области видимости класса, он возвращается к поиску пространства имен, но это точно такой же поиск пространства имен, который используется в определении функции, нет необходимости поддерживать новое состояние.Когда объявление using
найдено на уровне пространства имен, содержимое используемого пространства имен заносит в это пространство имен для всех поисков, включающих пространство имен.Если бы using namespace
было разрешено на уровне класса, результаты поиска в пространстве имен для одного и того же пространства имен были бы разными, в зависимости от того, откуда был запущен поиск, и это сделало бы реализацию поиска намного более сложной без дополнительного значения.
В любом случае, я рекомендую , а не , чтобы использовать декларацию using namespace
вообще.Это упрощает работу с кодом без необходимости помнить содержимое всех пространств имен.