Это ошибка в g ++ или clang ++ - PullRequest
4 голосов
/ 28 января 2020

Следующий код:

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

class B
{
  friend void f(A* p) { p->m = 32; }
};

Компилируется в версии clang 9.0.0-2, но не в версии g ++ 9.2.1

friend-test.cpp: In function ‘void f(A*)’:
friend-test.cpp:10:28: error: ‘int A::m’ is private within this context
   10 |   friend void f(A* p) { p->m = 32; }
      |                            ^
friend-test.cpp:5:7: note: declared private here
    5 |   int m;
      |       ^

Какой компилятор подходит?

Ответы [ 2 ]

8 голосов
/ 28 января 2020

G CC справа. Кажется, что в Clang есть ошибка.

[class.friend]

10 Дружба не является ни наследственной, ни переходной. [Пример:

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

class B {
  friend class C;
};

class C  {
  void f(A* p) {
    p->a++;         // error: C is not a friend of A despite being a friend of a friend
  }
};

class D : public B  {
  void f(A* p) {
    p->a++;         // error: D is not a friend of A despite being derived from a friend
  }
};

- конец примера]

Факт f друг B, а B, в свою очередь, друг A не означает, что f разрешен доступ к приватным частям A.

1 голос
/ 28 января 2020

Согласно стандарту C ++ 17 (14,3 друзей)

10 Дружба не наследуется и не является переходной

Таким образом, клан компилятора имеет ошибка.

Интересно отметить, что если определить функцию вне class B подобно

class B
{
    public:
    friend void f(A* p);
};

void f(A* p) { p->m = 32; }

, то в этом случае компилятор clang HEAD 10.0.0 выдает ошибку

rog.cc:18:19: error: 'm' is a private member of 'A'
void f(A* p) { p->m = 32; }
                  ^
prog.cc:9:7: note: implicitly declared private here
  int m;
      ^
1 error generated.

Так что, без всяких сомнений, в компиляторе есть ошибка.

...