объявление класса друга и использование директивы

Правильно ли сформирован следующий пример?

namespace N {
class A;
}
using namespace N;

class B {
int i;
friend class A;
};

namespace N {
class A {
B m;
int get() { return m.i; }
};
}

Этот пример успешно скомпилирован с Clang 3.5, но не с g ++ 4.8.1 со следующим:

main.cpp: In member function ‘int N::A::get()’:
main.cpp:7:9: error: ‘int B::i’ is private
int i;
^
main.cpp:14:30: error: within this context
int get() { return m.i; }
^

Стандарт C ++ 11 §7.3.1.2 p3 говорит,

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

В примере class A не является членом внутреннее пространство имен (то есть глобальное пространство имен), но class A вводится с помощью директивы в глобальном пространстве имен.

13

Решение

Хотя использование пространства имен N приводит к вытягиванию имени N :: A в глобальное пространство имен, оно не объявляет, что A в глобальном пространстве имен. Следовательно, дополнительный A в глобальном пространстве имен является другом B. clang не прав.

1

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

Делать N::A без квалификации friend из B вы бы использовали

friend A;

скорее, чем

friend class A;

При использовании разработанного спецификатора типа, т.е. class Aи именно в этой конкретной форме он вводит имя класса (см. 3.4.4 [basic.lookup.elab] параграф 2).

8

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