Следующий код отклоняется 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
}
Стандарт определяет интерпретацию с 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
будут найдены во вмещающей области пространства имен при поиске.
Из-за этого:
using namespace A;
using namespace B;
Обе функции f
находятся в области видимости. У них такая же подпись, так что вы ожидаете?
Это использование директивы:
using A::f();
Является избыточным.
using namespace B
f()
видны. Кроме того, вам не нужна точка с запятой после закрывающей скобки пространства имен.