Почему `использование A :: f` не работает должным образом?

0

Следующий код отклоняется VC++ и clang.

Почему using A::f не работает должным образом?

Есть ли способ скрыть некоторые имена в заданном пространстве имен?

namespace A
{
    int f()
    {
        return 1;
    }
};

namespace B
{
    int f()
    {
        return 2;
    }
};

using namespace A;
using namespace B;

using A::f; // I want to hide B::f and only use A::f, how to do?

int main()
{
    auto n = f(); // error : call to 'f' is ambiguous
}
  • 1
    Можете ли вы придумать заголовок, который не потребует от будущих посетителей называть свои пространства имен и переменные так же, как вы его нашли?
  • 2
    Почему вы ожидаете, что это сработает? Оба f() видны. Кроме того, вам не нужна точка с запятой после закрывающей скобки пространства имен.
Показать ещё 2 комментария
Теги:
namespaces
using

2 ответа

4

Стандарт определяет интерпретацию с using директивы. Акцент мой:

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

(С++ 11 §7.3.4/2)

Таким образом, после

using namespace A;
using namespace B;

неквалифицированный поиск имени f находит A::f и B::f как если бы они были объявлены в глобальном пространстве имен. Объявление using A::f вводит имя f в глобальное пространство имен таким же образом (хотя оно отличается тем, что оно фактически делает A::f членом глобального пространства имен), поэтому оно избыточно, поскольку неквалифицированный поиск идет, Дело в том, что поиск неквалифицированного имени для f находит как A::f и B::f в той же декларативной области.

Решение?

int main()
{
    using A::f;
    auto n = f(); // no longer ambiguous; finds A::f
}

Первое место, в котором просматривается неквалифицированный поиск имени, - это область блока main, поэтому он найдет только A::f, даже если A::f и B::f будут найдены во вмещающей области пространства имен при поиске.

2

Из-за этого:

using namespace A;
using namespace B;

Обе функции f находятся в области видимости. У них такая же подпись, так что вы ожидаете?

Это использование директивы:

using A::f();

Является избыточным.

  • 1
    очевидно, что OP был сбит с толку, потому что они волшебным образом ожидали, что избыточная директива переопределит using namespace B
  • 0
    @djechlin: Хорошо, это неправильно, и я так и сказал. В чем ваша точка зрения? Тебе просто не нравится, как я это сформулировал? Это правда, что я не пошел к спецификации.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню