clang++, g++ и MSVC не согласны с этим кодом:
class A {
private:
enum class E { NO, YES };
class B {
private:
friend E f1() { return E::YES; }
// friend E f2();
};
};
// A::E f2() { return A::E::YES; }
int main() {}
clang++ принимает код, как показано. g++ и MSVC жалуются в f1 что A::E недоступен. Если функция f2 не закомментирована, все три компилятора при своем определении жалуются, что A::E недоступен.
Действительно ли f1 действителен?
Соответствующие Стандартные части, которые я нашел:
Вложенный класс является членом, и поэтому имеет те же права доступа, что и любой другой член.
Хотя это само по себе не означает, что друзья вложенного класса имеют все те же права, что и вложенный класс.
Доступ к члену зависит от класса, в котором он назван. Этот класс именования является классом, в котором имя члена было найдено и найдено. Член
mдоступен в точке R при названии в классеNесли
mкак членNявляется публичным, или
mкак членNявляется частным, а R встречается в члене или друге классаN, или
mкак членNзащищен, и..., илисуществует базовый класс
BизNкоторый доступен в R, иmдоступен в R, когда назван в классеB
Таким образом, f2 недопустим, потому что класс именования для A::E определенно равен A, базовые классы не задействованы, и определение f2 не является членом или другом A и не "встречается" в члене или друге. из A.
В f1 класс именования для неквалифицированного E также равен A ([basic.lookup.unqual] говорит, что поиск имени E в классе A::B выполняется первым, но он там не "найден", поэтому выполняется поиск в классе A, и член найден.) Но я полагаю, что главный вопрос в том, встречается ли определение f1 в члене A? Этот член, если так, должен быть class A::B