Вопрос по namespaces, c++, language-lawyer – Использование пространства имен вызывает скрытие имени?

12

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

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 C::X), то это решитC::X как и ожидалось.

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

A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. During unqualified name lookup (3.4.1), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace.

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

@ Дэвид Родр - guez - dribeas: О, это бы объяснило ... K-ballo
Может быть, ключ вthe names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace, Не будет ли это::? И если так, будетA::X не может быть найден первым (поиск идет из внутреннего пространства имен) ... хотя и не уверен, но g ++ также подхватываетA::X, так что, этоvery согласовано между компиляторами. David Rodríguez - dribeas

Ваш Ответ

1   ответ
6

using directive кажетсяsomehow Понятно, что вы видите ожидаемое поведение:

7.3.4p2 A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. During unqualified name lookup (3.4.1), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace.

7.3.4p3 A using-directive does not add any members to the declarative region in which it appears.

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

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

7.3.4p4 [...] For another example

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-directive не прячется, а скрывается.

я избегаюusing-directives в моем реальном коде это просто попытка «найти, где живет класс»; используя правила поиска имени. K-ballo
Итак, для моего второго вопроса, я предполагаю, чтоis возможно скрыть имена с помощью директив, но только если они находятся во внешней области видимости общего предка пространства имен. K-ballo
Я бы так сказал. Во всяком случае, я бы избегалusing-directives в целом, и только использоватьusing-declarations редко. Поиск становится намного сложнее, и становится сложнее определить, что именно используется, где он определен ... Если вам нужно упростить использование сложных вложенных пространств имен, рассмотритеnamespace aliases.

Похожие вопросы