Форвардная декларация C ++ и дружба в пространстве имен

В соответствии с 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?

6

Решение

В конце параграфа говорится:

При поиске предварительного объявления класса или функции, объявленной в качестве друга, и когда имя класса или функции друга не является ни квалифицированным именем, ни идентификатором шаблона, области за пределами самого внутреннего окружающего пространства имен не рассматриваются.

Вот почему ::h не учитывается: это не полное имя и не идентификатор шаблона. Это также, почему ‘:: f2` считается, потому что это идентификатор шаблона.

2

Другие решения

Я думаю, что внутренние объявления скрывают те, что находятся в глобальном пространстве имен. Кроме того, сами объявления друзей являются предварительными объявлениями, поэтому они скрывают те, что находятся в глобальном пространстве имен, а не просто «ссылаются» на эти функции.

Ссылаясь на 3.3.10.1 «Сокрытие имени» в N3485:

Имя может быть скрыто явным объявлением того же имени в
вложенная декларативная область или производный класс (10.2).

11.3.4 Друзья:

Функция, впервые объявленная в объявлении друга, имеет внешнюю связь
(3.5). В противном случае функция сохраняет прежнюю связь (7.1.1).

Глядя на 3.5.2:

Когда имя имеет внешнюю связь, сущность, которую оно обозначает, может быть
упоминается по именам из областей других переводческих единиц или из
другие возможности того же переводчика.

1

По вопросам рекламы [email protected]