Ответ 1
Это работает для выражения вызова функции:
f(a);
поскольку пространство имен, к которому принадлежит X::A
, включено в поиск функции f
из-за зависимого от аргумента поиска (ADL), cppreference объясняет ADL следующим образом:
Аргумент-зависимый поиск, также известный как ADL или поиск Koenig, является набор правил поиска неквалифицированных имен функций в выражения функции-вызова, включая неявные вызовы функций для перегруженных операторов. Эти имена функций отображаются в пространства имен их аргументов в дополнение к областям и пространствам имен рассмотренный обычным безусловным поиском имен.
Аргумент-зависимый поиск позволяет использовать определенные операторы в другом пространстве имен
Это описано в черновик проекта С++ 3.4.2
Поиск по зависимым от аргументам имени:
Когда постфиксное выражение в вызове функции (5.2.2) является неквалифицированным-id, другие пространства имен не считаются во время обычного неквалифицированного поиска (3.4.1) можно искать и в этих пространствах имен пространство имен объявления друзей или функции (11.3), которые не отображаются в других местах, могут быть найдены
и далее:
Для каждого аргумента типа типа T в вызове функции существует набор нулевых или более связанных пространств имен и набор нулевых или более связанных классов. Определены наборы пространств имен и классов полностью по типам аргументов функции (и пространству имен любого аргумента шаблона шаблона).
и включает следующую марку:
Если T - тип класса (включая союзы), его ассоциированные классы: сам класс; класс которого он является член, если таковой имеется; и его прямые и косвенные базовые классы. Его ассоциированные пространства имен - это пространства имен из которых ассоциированные классы являются членами. [...]
а далее - аналогичный пример вашей проблемы:
namespace NS {
class T { };
void f(T);
void g(T, int);
}
NS::T parm;
void g(NS::T, float);
int main() {
f(parm); // OK: calls NS::f
extern void g(NS::T, float);
g(parm, 1); // OK: calls g(NS::T, float)
}
Выражение вызова функции:
g(5);
не работает, поскольку ADL не добавляет пространства имен для аргументов, которые являются фундаментальными типами.
Herb Sutter охватывает ADL в Gotw # 30 и в Что в Класс? - Принцип интерфейса.