Я понимаю, что следующий фрагмент кода C ++ должен привести к ошибке в определении g
, потому что p.t.x
является закрытым и не может быть доступен там.
class P {
class T {
int x;
friend class P;
};
T t;
friend void g(P &p);
};
void g(P &p) { p.t.x = 42; }
Что меня удивляет, так это следующее сниппет. Он отличается только тем, что определение функции друга g
теперь происходит внутри class P
.
class P {
class T {
int x;
friend class P;
};
T t;
friend void g(P &p) { p.t.x = 42; }
};
Clang ++ (оба 6.0. 0-1ubuntu2 и версия Apple clang-1100.0.33.8) компилирует последнюю без ошибок, тогда как GNU C ++ (7.5.0-3ubuntu1 ~ 18.04) выдает ту же ошибку, что и в предыдущем фрагменте.
Я понимаю, что функция g
, определенная в последнем случае, не относится к той же области, что и определенная в первом случае (см. связанный вопрос и более старое более длинное обсуждение ), и это только видно через ADL. Но я думаю, что здесь я спрашиваю иначе: должно ли объявление friend class P
в классе T
распространяться на тело функции друга g
или нет?
Соответствующая часть стандарта C ++ ( В §11.3 или §11.9.3 в более поздних drafts ) говорится, что:
7 ... Функция друга, определенная в классе, входит в (лексическую) область видимости класс, в котором он определен. Друга функция, определенная вне класса, не является (6.5.1).
Так что я понимаю, что Clang ++ и GNU C ++ по-разному интерпретируют то, что подразумевается под "лексической областью действия" (см. Также этот ответ к предыдущему связанному вопросу). Clang ++, похоже, компилирует g
, как если бы он был другом класса T
, возможно потому, что он входит в лексическую область класса P
, который является другом класса T
, тогда как GNU C ++ этого не делает.
- Есть ли ошибка в одном из двух компиляторов?
- Если да, то какой?
- Независимо от ответов на предыдущие вопросы, разве это не то, что стандарт должен формализоваться лучше?