Обычно, когда у вас есть using
, , «используемое» имя имеет приоритет :
namespace N { int x = 0; }
int x = 1;
int main() {
using N::x;
cout << x;
}
// Output: 0
Однако, зависящий от аргументов поиск может испортить это :
namespace N {
struct T {};
void f(T) {}
}
namespace M {
void f(N::T) {}
}
int main() {
using M::f;
N::T o;
f(o); // <--- error: call of overloaded 'f(N::T&)' is ambiguous
}
Итак, если у вас возникли проблемы, определите ваше собственное пространство имен (в данном примере M
) явно :
namespace N {
struct T {};
void f(T) { cout << "N::f"; }
}
namespace M {
void f(N::T) { cout << "M::f"; }
}
int main() {
using M::f;
N::T o;
M::f(o); // <--- Output: "M::f"
}
В несколько странной ситуации вы также можете использовать скобки для предотвращения ADL :
namespace N {
struct T {};
void f(T) { cout << "N::f"; }
}
namespace M {
void f(N::T) { cout << "M::f"; }
}
int main() {
using M::f;
N::T o;
(f)(o); // <--- Output: "M::f"
}
Объяснение
[n3290: 3.4.1/1]:
[re: поиск безусловного имени] Во всех случаях
перечисленные в п. 3.4.1, , в областях ищется объявление в
порядок указан в каждой из соответствующих категорий; поиск имени заканчивается
как только найдена декларация на имя . Если нет декларации
найдена, программа некорректна.
[n3290: 3.4.1/2]:
[т.е. первый приоритет] Заявления от
пространство имен, назначенное директивой using *, становится видимым в пространстве имен
включая директиву об использовании ; см. 7.3.4. Для целей
правила поиска имени без оговорок, описанные в п. 3.4.1, объявления
из пространства имен, назначенного директивой using
члены этого вмещающего пространства имен.
[n3290: 3.4.2/1]:
[re: аргумент-зависимый поиск] Когда постфиксное выражение в вызове функции
(5.2.2) является безусловным идентификатором , других пространств имен, не рассматриваемых во время
обычный неквалифицированный поиск (3.4.1) может быть найден , и в тех
пространства имен, объявления дружественных функций в области имен (11.3) not
в противном случае видимый может быть найден. Эти модификации в поиске
зависит от типов аргументов (и для шаблона шаблона
arguments, пространство имен аргумента шаблона).
т.е. Обычный поиск останавливается на имени, которое вы вводите в область действия с помощью using
, но когда ADL вступает в игру, другие имена также добавляются в набор кандидатов, вызывая двусмысленность между двумя именами.