The following code:
class A
{
friend class B;
int m;
};
class B
{
friend void f(A* p) { p->m = 32; }
};
Compiles in clang version 9.0.0-2, but not in g++ version 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;
| ^
Which compiler is right?
GCC is in the right. Clang appears to have a bug.
[class.friend]
10 Friendship is neither inherited nor transitive. [ Example:
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 } };
— end example ]
The fact f
is a friend of B
and B
is in turn a friend of A
doesn't mean f
is allowed to access A
's private parts.
According to the C++ 17 Standard (14.3 Friends)
10 Friendship is neither inherited nor transitive
Thus the compiler clang has a bug.
It is interesting to note that if to define the function outside the class B
like
class B
{
public:
friend void f(A* p);
};
void f(A* p) { p->m = 32; }
then in this case the compiler clang HEAD 10.0.0 issues an error
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.
So without any doubts the compiler has a bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With