Почему нельзя переслать объявленный класс друга в класс - PullRequest
0 голосов
/ 27 августа 2018

Следующий код не компилируется:

struct X {
  friend class Y;
  Y* ptr;
};

cppreference описывает ситуацию как

... Если имя класса, используемого в объявлении друга, еще не объявлено, оно объявлено на месте.

Если «пятно» означает, где объявляются дружеские отношения, тогда можно объявить участника Y* ptr. Почему он не компилируется? Где в стандарте это запрещено?

Ответы [ 3 ]

0 голосов
/ 27 августа 2018

В дополнение к ответу @dasblinkenlight, примечание в 3.3.2 Точка объявления горит. 10 явно говорит, что объявление друга не вводит (и, следовательно, не "предварительное объявление") имя класса:

10 [Примечание: объявления друзей относятся к функциям или классам, которые члены ближайшего окружающего пространства имен, но они не вводят новые имена в этом пространстве имен ([namespace.memdef]).

0 голосов
/ 27 августа 2018

Один из способов исправить этот код - просто добавить class ключевое слово :

struct X {
    friend class Y;
    class Y* ptr;
};

Это приведет к объявлению class Y в глобальной области, если X находится в глобальной области.

0 голосов
/ 27 августа 2018

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

7.3.1.2.3 Каждое имя, впервые объявленное в пространстве имен, является членом этого пространства имен. Если объявление друга в нелокальном классе сначала объявляет класс, функцию, шаблон класса или шаблон функции, то друг является членом внутреннего вложенного пространства имен. Объявление друга само по себе не делает имя видимым для неквалифицированного или квалифицированного поиска.

Часть о том, что имя невидимо для неквалифицированного или квалифицированного поиска, по существу означает, что имя не ведет себя как предварительное объявление.

...