Подтвердить что ты не робот

Используется ли использование пространства имен для скрытия имени?

Рассмотрим следующий код:

namespace C {
    class X {};
}

namespace A {
    class X {};

    namespace B {
        using namespace C;

        X x;
    }
}

Я ожидал, что тип x будет C::X из-за директивы using namespace, но вместо этого VS2010 и онлайн-компилятор LLVM/Clang разрешают x в пространстве имен B быть A::X, Изменив директиву using с помощью объявления using (using C::X), тогда он разрешает C::X, как ожидалось.

В стандарте говорится об использовании директив [7.3.4.2]:

В директиве using указано, что имена в номенклатурном пространстве имен могут использоваться в области, в которой появляется директива using после директивы use. При неквалифицированном поиске имени (3.4.1) имена отображаются так, как если бы они были объявлены в ближайшем охватывающем пространстве имен, которое содержит как директиву-использование, так и номинированное пространство имен.

Мое прочтение этого состоит в том, что C::X должно выглядеть так, как будто объявлено в пространстве имен B, эффективно скрывая A::X. Какой раздел стандарта находится за этой несогласованностью между использованием директив и использованием деклараций? Есть ли способ скрыть имя из внешней области с помощью директивы using?

4b9b3361

Ответ 1

Глава по использованию директивы кажется как-то ясным, что вы видите ожидаемое поведение:

7.3.4p2 Директива using указывает, что имена в номенклатурном пространстве имен могут использоваться в области, в которой появляется директива using после директивы use. При поиске неквалифицированного имени (3.4.1) имена отображаются так, как если бы они были объявлены в ближайшем охватывающем пространстве имен, которое содержит и директиву использования и назначенное пространство имен.

7.3.4p3 Директива using не добавляет никаких членов в декларативную область, в которой она появляется.

То есть, директива using добавляет членов пространства имен в набор поиска общего предка пространства имен директивы и используемого пространства имен, а не непосредственно в область, в которой используется директива use. Это явно указано во второй цитате: она не добавляет никаких членов в декларативную область директивы use.

Позже есть пример, который призван проиллюстрировать что-то еще, но на самом деле показывает это:

7.3.4p4 [...] Для другого примера

namespace A {
  int i;
}
namespace B {
  int i;
  int j;
  namespace C {
    namespace D {
      using namespace A;
      int j;
      int k;
      int a = i; // B::i hides A::i
    }

Этот последний пример используется для уточнения транзитивности (и содержит больше кода), но он фактически эквивалентен вашему коду после удаления дополнительного кода.

Итак, кажется, что в вашем случае директива using не скрывается, а скорее скрывается.