В соответствии с 7.3.1.2 определениями членов пространства имен в стандарте C ++ ISO / IEC 14882: 2003 (E)
Каждое имя, впервые объявленное в пространстве имен, является членом этого
Пространство имен. Если объявление друга в нелокальном классе сначала объявляет
класс или функция (это означает, что имя класса или
функция не определена) класс или функция друга является членом
самое внутреннее вмещающее пространство имен.
// Assume f and g have not yet been defined.
void h(int);
template <class T> void f2(T);
namespace A {
class X {
friend void f(X); // A::f(X) is a friend
class Y {
friend void g(); // A::g is a friend
friend void h(int); // A::h is a friend
// ::h not considered
friend void f2<>(int); // ::f2<>(int) is a friend
};
};
// A::f, A::g and A::h are not visible here
X x;
void g() { f(x); } // definition of A::g
void f(X) { /* ... */} // definition of A::f
void h(int) { /* ... */ } // definition of A::h
// A::f, A::g and A::h are visible here and known to be friends
}
поскольку void h(int);
сначала объявлен в глобальном пространстве имен, он является членом глобального пространства имен. Почему декларация друга friend void h(int);
в class Y
рассматривать A::h
скорее, чем ::h
?
В конце параграфа говорится:
При поиске предварительного объявления класса или функции, объявленной в качестве друга, и когда имя класса или функции друга не является ни квалифицированным именем, ни идентификатором шаблона, области за пределами самого внутреннего окружающего пространства имен не рассматриваются.
Вот почему ::h
не учитывается: это не полное имя и не идентификатор шаблона. Это также, почему ‘:: f2` считается, потому что это идентификатор шаблона.
Я думаю, что внутренние объявления скрывают те, что находятся в глобальном пространстве имен. Кроме того, сами объявления друзей являются предварительными объявлениями, поэтому они скрывают те, что находятся в глобальном пространстве имен, а не просто «ссылаются» на эти функции.
Ссылаясь на 3.3.10.1 «Сокрытие имени» в N3485:
Имя может быть скрыто явным объявлением того же имени в
вложенная декларативная область или производный класс (10.2).
11.3.4 Друзья:
Функция, впервые объявленная в объявлении друга, имеет внешнюю связь
(3.5). В противном случае функция сохраняет прежнюю связь (7.1.1).
Глядя на 3.5.2:
Когда имя имеет внешнюю связь, сущность, которую оно обозначает, может быть
упоминается по именам из областей других переводческих единиц или из
другие возможности того же переводчика.